Esempio n. 1
0
static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                                 pollable *p, gpr_timespec now,
                                 gpr_timespec deadline) {
  int timeout = poll_deadline_to_millis_timeout(deadline, now);

  if (GRPC_TRACER_ON(grpc_polling_trace)) {
    gpr_log(GPR_DEBUG, "PS:%p poll %p for %dms", pollset, p, timeout);
  }

  if (timeout != 0) {
    GRPC_SCHEDULING_START_BLOCKING_REGION;
  }
  int r;
  do {
    r = epoll_wait(p->epfd, pollset->events, MAX_EPOLL_EVENTS, timeout);
  } while (r < 0 && errno == EINTR);
  if (timeout != 0) {
    GRPC_SCHEDULING_END_BLOCKING_REGION;
  }

  if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");

  if (GRPC_TRACER_ON(grpc_polling_trace)) {
    gpr_log(GPR_DEBUG, "PS:%p poll %p got %d events", pollset, p, r);
  }

  pollset->event_cursor = 0;
  pollset->event_count = r;

  return GRPC_ERROR_NONE;
}
Esempio n. 2
0
/* Return true if this thread should poll */
static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker,
                         grpc_pollset_worker **worker_hdl, gpr_timespec *now,
                         gpr_timespec deadline) {
  bool do_poll = true;
  if (worker_hdl != NULL) *worker_hdl = worker;
  worker->initialized_cv = false;
  worker->kicked = false;
  worker->pollset = pollset;
  worker->pollable = pollset->current_pollable;

  if (pollset_is_pollable_fd(pollset, worker->pollable)) {
    REF_BY((grpc_fd *)worker->pollable, 2, "one_poll");
  }

  worker_insert(&pollset->root_worker, PWL_POLLSET, worker);
  if (!worker_insert(&worker->pollable->root_worker, PWL_POLLABLE, worker)) {
    worker->initialized_cv = true;
    gpr_cv_init(&worker->cv);
    if (worker->pollable != &pollset->pollable) {
      gpr_mu_unlock(&pollset->pollable.po.mu);
    }
    if (GRPC_TRACER_ON(grpc_polling_trace) &&
        worker->pollable->root_worker != worker) {
      gpr_log(GPR_DEBUG, "PS:%p wait %p w=%p for %dms", pollset,
              worker->pollable, worker,
              poll_deadline_to_millis_timeout(deadline, *now));
    }
    while (do_poll && worker->pollable->root_worker != worker) {
      if (gpr_cv_wait(&worker->cv, &worker->pollable->po.mu, deadline)) {
        if (GRPC_TRACER_ON(grpc_polling_trace)) {
          gpr_log(GPR_DEBUG, "PS:%p timeout_wait %p w=%p", pollset,
                  worker->pollable, worker);
        }
        do_poll = false;
      } else if (worker->kicked) {
        if (GRPC_TRACER_ON(grpc_polling_trace)) {
          gpr_log(GPR_DEBUG, "PS:%p wakeup %p w=%p", pollset, worker->pollable,
                  worker);
        }
        do_poll = false;
      } else if (GRPC_TRACER_ON(grpc_polling_trace) &&
                 worker->pollable->root_worker != worker) {
        gpr_log(GPR_DEBUG, "PS:%p spurious_wakeup %p w=%p", pollset,
                worker->pollable, worker);
      }
    }
    if (worker->pollable != &pollset->pollable) {
      gpr_mu_unlock(&worker->pollable->po.mu);
      gpr_mu_lock(&pollset->pollable.po.mu);
      gpr_mu_lock(&worker->pollable->po.mu);
    }
    *now = gpr_now(now->clock_type);
  }

  return do_poll && pollset->shutdown_closure == NULL &&
         pollset->current_pollable == worker->pollable;
}
Esempio n. 3
0
static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx,
                                     grpc_chttp2_transport *t) {
  if (t->is_first_frame &&
      t->incoming_frame_type != GRPC_CHTTP2_FRAME_SETTINGS) {
    char *msg;
    gpr_asprintf(
        &msg, "Expected SETTINGS frame as the first frame, got frame type %d",
        t->incoming_frame_type);
    grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
    gpr_free(msg);
    return err;
  }
  t->is_first_frame = false;
  if (t->expect_continuation_stream_id != 0) {
    if (t->incoming_frame_type != GRPC_CHTTP2_FRAME_CONTINUATION) {
      char *msg;
      gpr_asprintf(&msg, "Expected CONTINUATION frame, got frame type %02x",
                   t->incoming_frame_type);
      grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
      gpr_free(msg);
      return err;
    }
    if (t->expect_continuation_stream_id != t->incoming_stream_id) {
      char *msg;
      gpr_asprintf(
          &msg,
          "Expected CONTINUATION frame for grpc_chttp2_stream %08x, got "
          "grpc_chttp2_stream %08x",
          t->expect_continuation_stream_id, t->incoming_stream_id);
      grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
      gpr_free(msg);
      return err;
    }
    return init_header_frame_parser(exec_ctx, t, 1);
  }
  switch (t->incoming_frame_type) {
    case GRPC_CHTTP2_FRAME_DATA:
      return init_data_frame_parser(exec_ctx, t);
    case GRPC_CHTTP2_FRAME_HEADER:
      return init_header_frame_parser(exec_ctx, t, 0);
    case GRPC_CHTTP2_FRAME_CONTINUATION:
      return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
          "Unexpected CONTINUATION frame");
    case GRPC_CHTTP2_FRAME_RST_STREAM:
      return init_rst_stream_parser(exec_ctx, t);
    case GRPC_CHTTP2_FRAME_SETTINGS:
      return init_settings_frame_parser(exec_ctx, t);
    case GRPC_CHTTP2_FRAME_WINDOW_UPDATE:
      return init_window_update_frame_parser(exec_ctx, t);
    case GRPC_CHTTP2_FRAME_PING:
      return init_ping_parser(exec_ctx, t);
    case GRPC_CHTTP2_FRAME_GOAWAY:
      return init_goaway_parser(exec_ctx, t);
    default:
      if (GRPC_TRACER_ON(grpc_http_trace)) {
        gpr_log(GPR_ERROR, "Unknown frame type %02x", t->incoming_frame_type);
      }
      return init_skip_frame_parser(exec_ctx, t, 0);
  }
}
Esempio n. 4
0
static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx,
                                     grpc_chttp2_transport *t, grpc_slice slice,
                                     int is_last) {
  grpc_chttp2_stream *s = t->incoming_stream;
  grpc_error *err = t->parser(exec_ctx, t->parser_data, t, s, slice, is_last);
  if (err == GRPC_ERROR_NONE) {
    return err;
  } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
    if (GRPC_TRACER_ON(grpc_http_trace)) {
      const char *msg = grpc_error_string(err);
      gpr_log(GPR_ERROR, "%s", msg);
    }
    grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
    if (s) {
      s->forced_close_error = err;
      grpc_slice_buffer_add(
          &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
                                                  GRPC_HTTP2_PROTOCOL_ERROR,
                                                  &s->stats.outgoing));
    } else {
      GRPC_ERROR_UNREF(err);
    }
  }
  return err;
}
Esempio n. 5
0
static grpc_error *fill_in_metadata(grpc_exec_ctx *exec_ctx, inproc_stream *s,
                                    const grpc_metadata_batch *metadata,
                                    uint32_t flags, grpc_metadata_batch *out_md,
                                    uint32_t *outflags, bool *markfilled) {
  if (GRPC_TRACER_ON(grpc_inproc_trace)) {
    log_metadata(metadata, s->t->is_client, outflags != NULL);
  }

  if (outflags != NULL) {
    *outflags = flags;
  }
  if (markfilled != NULL) {
    *markfilled = true;
  }
  grpc_error *error = GRPC_ERROR_NONE;
  for (grpc_linked_mdelem *elem = metadata->list.head;
       (elem != NULL) && (error == GRPC_ERROR_NONE); elem = elem->next) {
    grpc_linked_mdelem *nelem = gpr_arena_alloc(s->arena, sizeof(*nelem));
    nelem->md = grpc_mdelem_from_slices(
        exec_ctx, grpc_slice_intern(GRPC_MDKEY(elem->md)),
        grpc_slice_intern(GRPC_MDVALUE(elem->md)));

    error = grpc_metadata_batch_link_tail(exec_ctx, out_md, nelem);
  }
  return error;
}
Esempio n. 6
0
void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
                                 grpc_connectivity_state_tracker *tracker,
                                 grpc_connectivity_state state,
                                 grpc_error *error, const char *reason) {
  grpc_connectivity_state cur =
      (grpc_connectivity_state)gpr_atm_no_barrier_load(
          &tracker->current_state_atm);
  grpc_connectivity_state_watcher *w;
  if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) {
    const char *error_string = grpc_error_string(error);
    gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker,
            tracker->name, grpc_connectivity_state_name(cur),
            grpc_connectivity_state_name(state), reason, error, error_string);
  }
  switch (state) {
    case GRPC_CHANNEL_INIT:
    case GRPC_CHANNEL_CONNECTING:
    case GRPC_CHANNEL_IDLE:
    case GRPC_CHANNEL_READY:
      GPR_ASSERT(error == GRPC_ERROR_NONE);
      break;
    case GRPC_CHANNEL_SHUTDOWN:
    case GRPC_CHANNEL_TRANSIENT_FAILURE:
      GPR_ASSERT(error != GRPC_ERROR_NONE);
      break;
  }
  GRPC_ERROR_UNREF(tracker->current_error);
  tracker->current_error = error;
  if (cur == state) {
    return;
  }
  GPR_ASSERT(cur != GRPC_CHANNEL_SHUTDOWN);
  gpr_atm_no_barrier_store(&tracker->current_state_atm, state);
  while ((w = tracker->watchers) != NULL) {
    *w->current = state;
    tracker->watchers = w->next;
    if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) {
      gpr_log(GPR_DEBUG, "NOTIFY: %p %s: %p", tracker, tracker->name,
              w->notify);
    }
    GRPC_CLOSURE_SCHED(exec_ctx, w->notify,
                       GRPC_ERROR_REF(tracker->current_error));
    gpr_free(w);
  }
}
Esempio n. 7
0
static void finish_send_message(grpc_exec_ctx *exec_ctx,
                                grpc_call_element *elem) {
  call_data *calld = elem->call_data;
  int did_compress;
  grpc_slice_buffer tmp;
  grpc_slice_buffer_init(&tmp);
  did_compress = grpc_msg_compress(exec_ctx, calld->compression_algorithm,
                                   &calld->slices, &tmp);
  if (did_compress) {
    if (GRPC_TRACER_ON(grpc_compression_trace)) {
      char *algo_name;
      const size_t before_size = calld->slices.length;
      const size_t after_size = tmp.length;
      const float savings_ratio = 1.0f - (float)after_size / (float)before_size;
      GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm,
                                                 &algo_name));
      gpr_log(GPR_DEBUG, "Compressed[%s] %" PRIuPTR " bytes vs. %" PRIuPTR
                         " bytes (%.2f%% savings)",
              algo_name, before_size, after_size, 100 * savings_ratio);
    }
    grpc_slice_buffer_swap(&calld->slices, &tmp);
    calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
  } else {
    if (GRPC_TRACER_ON(grpc_compression_trace)) {
      char *algo_name;
      GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm,
                                                 &algo_name));
      gpr_log(GPR_DEBUG,
              "Algorithm '%s' enabled but decided not to compress. Input size: "
              "%" PRIuPTR,
              algo_name, calld->slices.length);
    }
  }

  grpc_slice_buffer_destroy_internal(exec_ctx, &tmp);

  grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices,
                                calld->send_flags);
  calld->send_op->payload->send_message.send_message =
      &calld->replacement_stream.base;
  calld->post_send = calld->send_op->on_complete;
  calld->send_op->on_complete = &calld->send_done;

  grpc_call_next_op(exec_ctx, elem, calld->send_op);
}
Esempio n. 8
0
static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp,
                               grpc_mdelem md) {
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
  grpc_chttp2_stream *s = t->incoming_stream;

  GPR_TIMER_BEGIN("on_trailing_header", 0);

  GPR_ASSERT(s != NULL);

  if (GRPC_TRACER_ON(grpc_http_trace)) {
    char *key = grpc_slice_to_c_string(GRPC_MDKEY(md));
    char *value =
        grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
    gpr_log(GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id,
            t->is_client ? "CLI" : "SVR", key, value);
    gpr_free(key);
    gpr_free(value);
  }

  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
      !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
    /* TODO(ctiller): check for a status like " 0" */
    s->seen_error = true;
  }

  const size_t new_size = s->metadata_buffer[1].size + GRPC_MDELEM_LENGTH(md);
  const size_t metadata_size_limit =
      t->settings[GRPC_ACKED_SETTINGS]
                 [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
  if (new_size > metadata_size_limit) {
    gpr_log(GPR_DEBUG,
            "received trailing metadata size exceeds limit (%" PRIuPTR
            " vs. %" PRIuPTR ")",
            new_size, metadata_size_limit);
    grpc_chttp2_cancel_stream(
        exec_ctx, t, s,
        grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
                               "received trailing metadata size exceeds limit"),
                           GRPC_ERROR_INT_GRPC_STATUS,
                           GRPC_STATUS_RESOURCE_EXHAUSTED));
    grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
    s->seen_error = true;
    GRPC_MDELEM_UNREF(exec_ctx, md);
  } else {
    grpc_error *error = grpc_chttp2_incoming_metadata_buffer_add(
        exec_ctx, &s->metadata_buffer[1], md);
    if (error != GRPC_ERROR_NONE) {
      grpc_chttp2_cancel_stream(exec_ctx, t, s, error);
      grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
      s->seen_error = true;
      GRPC_MDELEM_UNREF(exec_ctx, md);
    }
  }

  GPR_TIMER_END("on_trailing_header", 0);
}
Esempio n. 9
0
static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
                    int line) {
  if (GRPC_TRACER_ON(grpc_tcp_trace)) {
    gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
    gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
            "TCP   ref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
            val + 1);
  }
  gpr_ref(&tcp->refcount);
}
Esempio n. 10
0
static void secure_endpoint_ref(secure_endpoint *ep, const char *reason,
                                const char *file, int line) {
  if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) {
    gpr_atm val = gpr_atm_no_barrier_load(&ep->ref.count);
    gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
            "SECENDP   ref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep, reason, val,
            val + 1);
  }
  gpr_ref(&ep->ref);
}
Esempio n. 11
0
/* pollset->po.mu lock must be held by the caller before calling this.
   The function pollset_work() may temporarily release the lock (pollset->po.mu)
   during the course of its execution but it will always re-acquire the lock and
   ensure that it is held by the time the function returns */
static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                                grpc_pollset_worker **worker_hdl,
                                gpr_timespec now, gpr_timespec deadline) {
  grpc_pollset_worker worker;
  if (0 && GRPC_TRACER_ON(grpc_polling_trace)) {
    gpr_log(GPR_DEBUG, "PS:%p work hdl=%p worker=%p now=%" PRId64
                       ".%09d deadline=%" PRId64 ".%09d kwp=%d root_worker=%p",
            pollset, worker_hdl, &worker, now.tv_sec, now.tv_nsec,
            deadline.tv_sec, deadline.tv_nsec, pollset->kicked_without_poller,
            pollset->root_worker);
  }
  grpc_error *error = GRPC_ERROR_NONE;
  static const char *err_desc = "pollset_work";
  if (pollset->kicked_without_poller) {
    pollset->kicked_without_poller = false;
    return GRPC_ERROR_NONE;
  }
  if (pollset->current_pollable != &pollset->pollable) {
    gpr_mu_lock(&pollset->current_pollable->po.mu);
  }
  if (begin_worker(pollset, &worker, worker_hdl, &now, deadline)) {
    gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
    gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
    GPR_ASSERT(!pollset->shutdown_closure);
    append_error(&error, pollable_materialize(worker.pollable), err_desc);
    if (worker.pollable != &pollset->pollable) {
      gpr_mu_unlock(&worker.pollable->po.mu);
    }
    gpr_mu_unlock(&pollset->pollable.po.mu);
    if (pollset->event_cursor == pollset->event_count) {
      append_error(&error, pollset_epoll(exec_ctx, pollset, worker.pollable,
                                         now, deadline),
                   err_desc);
    }
    append_error(&error, pollset_process_events(exec_ctx, pollset, false),
                 err_desc);
    gpr_mu_lock(&pollset->pollable.po.mu);
    if (worker.pollable != &pollset->pollable) {
      gpr_mu_lock(&worker.pollable->po.mu);
    }
    gpr_tls_set(&g_current_thread_pollset, 0);
    gpr_tls_set(&g_current_thread_worker, 0);
    pollset_maybe_finish_shutdown(exec_ctx, pollset);
  }
  end_worker(exec_ctx, pollset, &worker, worker_hdl);
  if (worker.pollable != &pollset->pollable) {
    gpr_mu_unlock(&worker.pollable->po.mu);
  }
  if (grpc_exec_ctx_has_work(exec_ctx)) {
    gpr_mu_unlock(&pollset->pollable.po.mu);
    grpc_exec_ctx_flush(exec_ctx);
    gpr_mu_lock(&pollset->pollable.po.mu);
  }
  return error;
}
Esempio n. 12
0
/* expects pollsets locked, flag whether fd is locked or not */
static grpc_error *pollset_add_fd_locked(grpc_exec_ctx *exec_ctx,
                                         grpc_pollset *pollset, grpc_fd *fd,
                                         bool fd_locked) {
  static const char *err_desc = "pollset_add_fd";
  grpc_error *error = GRPC_ERROR_NONE;
  if (pollset->current_pollable == &g_empty_pollable) {
    if (GRPC_TRACER_ON(grpc_polling_trace))
      gpr_log(GPR_DEBUG,
              "PS:%p add fd %p; transition pollable from empty to fd", pollset,
              fd);
    /* empty pollable --> single fd pollable */
    pollset_kick_all(exec_ctx, pollset);
    pollset->current_pollable = &fd->pollable;
    if (!fd_locked) gpr_mu_lock(&fd->pollable.po.mu);
    append_error(&error, fd_become_pollable_locked(fd), err_desc);
    if (!fd_locked) gpr_mu_unlock(&fd->pollable.po.mu);
    REF_BY(fd, 2, "pollset_pollable");
  } else if (pollset->current_pollable == &pollset->pollable) {
    if (GRPC_TRACER_ON(grpc_polling_trace))
      gpr_log(GPR_DEBUG, "PS:%p add fd %p; already multipolling", pollset, fd);
    append_error(&error, pollable_add_fd(pollset->current_pollable, fd),
                 err_desc);
  } else if (pollset->current_pollable != &fd->pollable) {
    grpc_fd *had_fd = (grpc_fd *)pollset->current_pollable;
    if (GRPC_TRACER_ON(grpc_polling_trace))
      gpr_log(GPR_DEBUG,
              "PS:%p add fd %p; transition pollable from fd %p to multipoller",
              pollset, fd, had_fd);
    pollset_kick_all(exec_ctx, pollset);
    pollset->current_pollable = &pollset->pollable;
    if (append_error(&error, pollable_materialize(&pollset->pollable),
                     err_desc)) {
      pollable_add_fd(&pollset->pollable, had_fd);
      pollable_add_fd(&pollset->pollable, fd);
    }
    GRPC_CLOSURE_SCHED(exec_ctx,
                       GRPC_CLOSURE_CREATE(unref_fd_no_longer_poller, had_fd,
                                           grpc_schedule_on_exec_ctx),
                       GRPC_ERROR_NONE);
  }
  return error;
}
Esempio n. 13
0
static void alarm_unref_dbg(grpc_alarm *alarm, const char *reason,
                            const char *file, int line) {
  if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) {
    gpr_atm val = gpr_atm_no_barrier_load(&alarm->refs.count);
    gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
            "Alarm:%p  Unref %" PRIdPTR " -> %" PRIdPTR " %s", alarm, val,
            val - 1, reason);
  }

  alarm_unref(alarm);
}
Esempio n. 14
0
static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
                        bool due_to_completion, grpc_error *error) {
  if (due_to_completion) {
    grpc_timer_cancel(exec_ctx, &w->alarm);
  } else {
    grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(
        grpc_channel_get_channel_stack(w->channel));
    grpc_client_channel_watch_connectivity_state(
        exec_ctx, client_channel_elem,
        grpc_polling_entity_create_from_pollset(grpc_cq_pollset(w->cq)), NULL,
        &w->on_complete, NULL);
  }

  gpr_mu_lock(&w->mu);

  if (due_to_completion) {
    if (GRPC_TRACER_ON(grpc_trace_operation_failures)) {
      GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error));
    }
    GRPC_ERROR_UNREF(error);
    error = GRPC_ERROR_NONE;
  } else {
    if (error == GRPC_ERROR_NONE) {
      error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
          "Timed out waiting for connection state change");
    } else if (error == GRPC_ERROR_CANCELLED) {
      error = GRPC_ERROR_NONE;
    }
  }
  switch (w->phase) {
    case WAITING:
      GRPC_ERROR_REF(error);
      w->error = error;
      w->phase = READY_TO_CALL_BACK;
      break;
    case READY_TO_CALL_BACK:
      if (error != GRPC_ERROR_NONE) {
        GPR_ASSERT(!due_to_completion);
        GRPC_ERROR_UNREF(w->error);
        GRPC_ERROR_REF(error);
        w->error = error;
      }
      w->phase = CALLING_BACK_AND_FINISHED;
      grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->error, finished_completion, w,
                     &w->completion_storage);
      break;
    case CALLING_BACK_AND_FINISHED:
      GPR_UNREACHABLE_CODE(return );
      break;
  }
  gpr_mu_unlock(&w->mu);

  GRPC_ERROR_UNREF(error);
}
Esempio n. 15
0
grpc_connectivity_state grpc_connectivity_state_check(
    grpc_connectivity_state_tracker *tracker) {
  grpc_connectivity_state cur =
      (grpc_connectivity_state)gpr_atm_no_barrier_load(
          &tracker->current_state_atm);
  if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) {
    gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
            grpc_connectivity_state_name(cur));
  }
  return cur;
}
Esempio n. 16
0
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
                      const char *reason, const char *file, int line) {
  if (GRPC_TRACER_ON(grpc_tcp_trace)) {
    gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
    gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
            "TCP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
            val - 1);
  }
  if (gpr_unref(&tcp->refcount)) {
    tcp_free(exec_ctx, tcp);
  }
}
Esempio n. 17
0
void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) {
  if (GRPC_TRACER_ON(grpc_trace_stream_refcount)) {
    gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count);
    gpr_log(GPR_DEBUG, "%s %p:%p   REF %" PRIdPTR "->%" PRIdPTR " %s",
            refcount->object_type, refcount, refcount->destroy.cb_arg, val,
            val + 1, reason);
  }
#else
void grpc_stream_ref(grpc_stream_refcount *refcount) {
#endif
  gpr_ref_non_zero(&refcount->refs);
}
Esempio n. 18
0
static void secure_endpoint_unref(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
                                  const char *reason, const char *file,
                                  int line) {
  if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) {
    gpr_atm val = gpr_atm_no_barrier_load(&ep->ref.count);
    gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
            "SECENDP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep, reason, val,
            val - 1);
  }
  if (gpr_unref(&ep->ref)) {
    destroy(exec_ctx, ep);
  }
}
Esempio n. 19
0
static gpr_atm ref_mutate(grpc_lb_policy *c, gpr_atm delta,
                          int barrier REF_MUTATE_EXTRA_ARGS) {
  gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
                            : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
#ifndef NDEBUG
  if (GRPC_TRACER_ON(grpc_trace_lb_policy_refcount)) {
    gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
            "LB_POLICY: 0x%p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c,
            purpose, old_val, old_val + delta, reason);
  }
#endif
  return old_val;
}
Esempio n. 20
0
void grpc_cq_internal_ref(grpc_completion_queue *cq, const char *reason,
                          const char *file, int line) {
  if (GRPC_TRACER_ON(grpc_trace_cq_refcount)) {
    gpr_atm val = gpr_atm_no_barrier_load(&cq->owning_refs.count);
    gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
            "CQ:%p   ref %" PRIdPTR " -> %" PRIdPTR " %s", cq, val, val + 1,
            reason);
  }
#else
void grpc_cq_internal_ref(grpc_completion_queue *cq) {
#endif
  gpr_ref(&cq->owning_refs);
}
Esempio n. 21
0
static grpc_error *pollset_process_events(grpc_exec_ctx *exec_ctx,
                                          grpc_pollset *pollset, bool drain) {
  static const char *err_desc = "pollset_process_events";
  grpc_error *error = GRPC_ERROR_NONE;
  for (int i = 0; (drain || i < MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL) &&
                  pollset->event_cursor != pollset->event_count;
       i++) {
    int n = pollset->event_cursor++;
    struct epoll_event *ev = &pollset->events[n];
    void *data_ptr = ev->data.ptr;
    if (1 & (intptr_t)data_ptr) {
      if (GRPC_TRACER_ON(grpc_polling_trace)) {
        gpr_log(GPR_DEBUG, "PS:%p got pollset_wakeup %p", pollset, data_ptr);
      }
      append_error(&error, grpc_wakeup_fd_consume_wakeup(
                               (void *)((~(intptr_t)1) & (intptr_t)data_ptr)),
                   err_desc);
    } else {
      grpc_fd *fd = (grpc_fd *)data_ptr;
      bool cancel = (ev->events & (EPOLLERR | EPOLLHUP)) != 0;
      bool read_ev = (ev->events & (EPOLLIN | EPOLLPRI)) != 0;
      bool write_ev = (ev->events & EPOLLOUT) != 0;
      if (GRPC_TRACER_ON(grpc_polling_trace)) {
        gpr_log(GPR_DEBUG,
                "PS:%p got fd %p: cancel=%d read=%d "
                "write=%d",
                pollset, fd, cancel, read_ev, write_ev);
      }
      if (read_ev || cancel) {
        fd_become_readable(exec_ctx, fd, pollset);
      }
      if (write_ev || cancel) {
        fd_become_writable(exec_ctx, fd);
      }
    }
  }

  return error;
}
Esempio n. 22
0
bool grpc_connectivity_state_notify_on_state_change(
    grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
    grpc_connectivity_state *current, grpc_closure *notify) {
  grpc_connectivity_state cur =
      (grpc_connectivity_state)gpr_atm_no_barrier_load(
          &tracker->current_state_atm);
  if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) {
    if (current == NULL) {
      gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
              tracker->name, notify);
    } else {
      gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
              tracker->name, grpc_connectivity_state_name(*current),
              grpc_connectivity_state_name(cur), notify);
    }
  }
  if (current == NULL) {
    grpc_connectivity_state_watcher *w = tracker->watchers;
    if (w != NULL && w->notify == notify) {
      GRPC_CLOSURE_SCHED(exec_ctx, notify, GRPC_ERROR_CANCELLED);
      tracker->watchers = w->next;
      gpr_free(w);
      return false;
    }
    while (w != NULL) {
      grpc_connectivity_state_watcher *rm_candidate = w->next;
      if (rm_candidate != NULL && rm_candidate->notify == notify) {
        GRPC_CLOSURE_SCHED(exec_ctx, notify, GRPC_ERROR_CANCELLED);
        w->next = w->next->next;
        gpr_free(rm_candidate);
        return false;
      }
      w = w->next;
    }
    return false;
  } else {
    if (cur != *current) {
      *current = cur;
      GRPC_CLOSURE_SCHED(exec_ctx, notify,
                         GRPC_ERROR_REF(tracker->current_error));
    } else {
      grpc_connectivity_state_watcher *w =
          (grpc_connectivity_state_watcher *)gpr_malloc(sizeof(*w));
      w->current = current;
      w->notify = notify;
      w->next = tracker->watchers;
      tracker->watchers = w;
    }
    return cur == GRPC_CHANNEL_IDLE;
  }
}
Esempio n. 23
0
grpc_connectivity_state grpc_connectivity_state_get(
    grpc_connectivity_state_tracker *tracker, grpc_error **error) {
  grpc_connectivity_state cur =
      (grpc_connectivity_state)gpr_atm_no_barrier_load(
          &tracker->current_state_atm);
  if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) {
    gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
            grpc_connectivity_state_name(cur));
  }
  if (error != NULL) {
    *error = GRPC_ERROR_REF(tracker->current_error);
  }
  return cur;
}
Esempio n. 24
0
static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file,
                   int line) {
  if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
    gpr_log(GPR_DEBUG,
            "FD %d %p   ref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
            fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
            gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
  }
#else
#define REF_BY(fd, n, reason) ref_by(fd, n)
#define UNREF_BY(ec, fd, n, reason) unref_by(ec, fd, n)
static void ref_by(grpc_fd *fd, int n) {
#endif
  GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0);
}
Esempio n. 25
0
static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
                         grpc_error *error) {
  if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) {
    size_t i;
    for (i = 0; i < ep->read_buffer->count; i++) {
      char *data = grpc_dump_slice(ep->read_buffer->slices[i],
                                   GPR_DUMP_HEX | GPR_DUMP_ASCII);
      gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
      gpr_free(data);
    }
  }
  ep->read_buffer = NULL;
  GRPC_CLOSURE_SCHED(exec_ctx, ep->read_cb, error);
  SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read");
}
Esempio n. 26
0
grpc_alarm *grpc_alarm_create(void *reserved) {
  grpc_alarm *alarm = (grpc_alarm *)gpr_malloc(sizeof(grpc_alarm));

#ifndef NDEBUG
  if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) {
    gpr_log(GPR_DEBUG, "Alarm:%p created (ref: 1)", alarm);
  }
#endif

  gpr_ref_init(&alarm->refs, 1);
  grpc_timer_init_unset(&alarm->alarm);
  alarm->cq = NULL;
  GRPC_CLOSURE_INIT(&alarm->on_alarm, alarm_cb, alarm,
                    grpc_schedule_on_exec_ctx);
  return alarm;
}
Esempio n. 27
0
/* pollable must be materialized */
static grpc_error *pollable_add_fd(pollable *p, grpc_fd *fd) {
  grpc_error *error = GRPC_ERROR_NONE;
  static const char *err_desc = "pollable_add_fd";
  const int epfd = p->epfd;
  GPR_ASSERT(epfd != -1);

  if (GRPC_TRACER_ON(grpc_polling_trace)) {
    gpr_log(GPR_DEBUG, "add fd %p to pollable %p", fd, p);
  }

  gpr_mu_lock(&fd->orphaned_mu);
  if (fd->orphaned) {
    gpr_mu_unlock(&fd->orphaned_mu);
    return GRPC_ERROR_NONE;
  }
  struct epoll_event ev_fd = {
      .events = (uint32_t)(EPOLLET | EPOLLIN | EPOLLOUT | EPOLLEXCLUSIVE),
      .data.ptr = fd};
  if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd->fd, &ev_fd) != 0) {
    switch (errno) {
      case EEXIST:
        break;
      default:
        append_error(&error, GRPC_OS_ERROR(errno, "epoll_ctl"), err_desc);
    }
  }
  gpr_mu_unlock(&fd->orphaned_mu);

  return error;
}

/*******************************************************************************
 * Pollset Definitions
 */

GPR_TLS_DECL(g_current_thread_pollset);
GPR_TLS_DECL(g_current_thread_worker);

/* Global state management */
static grpc_error *pollset_global_init(void) {
  gpr_tls_init(&g_current_thread_pollset);
  gpr_tls_init(&g_current_thread_worker);
  pollable_init(&g_empty_pollable, PO_EMPTY_POLLABLE);
  return GRPC_ERROR_NONE;
}
Esempio n. 28
0
static void stream_list_add_tail(grpc_chttp2_transport *t,
                                 grpc_chttp2_stream *s,
                                 grpc_chttp2_stream_list_id id) {
  grpc_chttp2_stream *old_tail;
  GPR_ASSERT(!s->included[id]);
  old_tail = t->lists[id].tail;
  s->links[id].next = NULL;
  s->links[id].prev = old_tail;
  if (old_tail) {
    old_tail->links[id].next = s;
  } else {
    t->lists[id].head = s;
  }
  t->lists[id].tail = s;
  s->included[id] = 1;
  if (GRPC_TRACER_ON(grpc_trace_http2_stream_state)) {
    gpr_log(GPR_DEBUG, "%p[%d][%s]: add to %s", t, s->id,
            t->is_client ? "cli" : "svr", stream_list_id_string(id));
  }
}
Esempio n. 29
0
static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n,
                     const char *reason, const char *file, int line) {
  if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
    gpr_log(GPR_DEBUG,
            "FD %d %p unref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
            fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
            gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
  }
#else
static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n) {
#endif
  gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n);
  if (old == n) {
    GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_CREATE(fd_destroy, fd,
                                                     grpc_schedule_on_exec_ctx),
                       GRPC_ERROR_NONE);
  } else {
    GPR_ASSERT(old > n);
  }
}
Esempio n. 30
0
static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
                               grpc_chttp2_stream_list_id id) {
  GPR_ASSERT(s->included[id]);
  s->included[id] = 0;
  if (s->links[id].prev) {
    s->links[id].prev->links[id].next = s->links[id].next;
  } else {
    GPR_ASSERT(t->lists[id].head == s);
    t->lists[id].head = s->links[id].next;
  }
  if (s->links[id].next) {
    s->links[id].next->links[id].prev = s->links[id].prev;
  } else {
    t->lists[id].tail = s->links[id].prev;
  }
  if (GRPC_TRACER_ON(grpc_trace_http2_stream_state)) {
    gpr_log(GPR_DEBUG, "%p[%d][%s]: remove from %s", t, s->id,
            t->is_client ? "cli" : "svr", stream_list_id_string(id));
  }
}