Call list progress

pull/3423/head
Craig Tiller 10 years ago
parent 3ffd8220a1
commit dfff1b8126
  1. 6
      src/core/census/grpc_filter.c
  2. 5
      src/core/channel/channel_stack.c
  3. 6
      src/core/channel/channel_stack.h
  4. 9
      src/core/channel/client_channel.c
  5. 3
      src/core/channel/compress_filter.c
  6. 19
      src/core/channel/connected_channel.c
  7. 3
      src/core/channel/http_client_filter.c
  8. 3
      src/core/channel/http_server_filter.c
  9. 3
      src/core/channel/noop_filter.c
  10. 2
      src/core/client_config/lb_policies/pick_first.c
  11. 2
      src/core/client_config/resolvers/dns_resolver.c
  12. 2
      src/core/client_config/resolvers/sockaddr_resolver.c
  13. 18
      src/core/client_config/subchannel.c
  14. 6
      src/core/client_config/subchannel_factory.c
  15. 5
      src/core/client_config/subchannel_factory.h
  16. 5
      src/core/client_config/subchannel_factory_decorators/merge_channel_args.c
  17. 7
      src/core/httpcli/httpcli.c
  18. 6
      src/core/httpcli/httpcli.h
  19. 3
      src/core/iomgr/alarm.c
  20. 7
      src/core/iomgr/pollset.h
  21. 20
      src/core/iomgr/pollset_posix.c
  22. 1
      src/core/iomgr/resolve_address.h
  23. 3
      src/core/security/client_auth_filter.c
  24. 2
      src/core/security/google_default_credentials.c
  25. 3
      src/core/security/server_auth_filter.c
  26. 20
      src/core/security/server_secure_chttp2.c
  27. 22
      src/core/surface/call.c
  28. 3
      src/core/surface/call.h
  29. 19
      src/core/surface/channel.c
  30. 14
      src/core/surface/channel.h
  31. 40
      src/core/surface/channel_connectivity.c
  32. 60
      src/core/surface/channel_create.c
  33. 32
      src/core/surface/completion_queue.c
  34. 6
      src/core/surface/completion_queue.h
  35. 40
      src/core/surface/lame_client.c
  36. 14
      src/core/surface/secure_channel_create.c
  37. 288
      src/core/surface/server.c
  38. 9
      src/core/surface/server.h
  39. 36
      src/core/surface/server_chttp2.c
  40. 3
      src/core/transport/chttp2/frame_data.c
  41. 4
      src/core/transport/chttp2/frame_data.h
  42. 3
      src/core/transport/chttp2/frame_goaway.c
  43. 4
      src/core/transport/chttp2/frame_goaway.h
  44. 7
      src/core/transport/chttp2/frame_ping.c
  45. 4
      src/core/transport/chttp2/frame_ping.h
  46. 3
      src/core/transport/chttp2/frame_rst_stream.c
  47. 4
      src/core/transport/chttp2/frame_rst_stream.h
  48. 3
      src/core/transport/chttp2/frame_settings.c
  49. 4
      src/core/transport/chttp2/frame_settings.h
  50. 3
      src/core/transport/chttp2/frame_window_update.c
  51. 4
      src/core/transport/chttp2/frame_window_update.h
  52. 3
      src/core/transport/chttp2/hpack_parser.c
  53. 4
      src/core/transport/chttp2/hpack_parser.h
  54. 21
      src/core/transport/chttp2/internal.h
  55. 30
      src/core/transport/chttp2/parsing.c
  56. 22
      src/core/transport/chttp2/writing.c
  57. 284
      src/core/transport/chttp2_transport.c
  58. 5
      src/core/transport/chttp2_transport.h
  59. 5
      src/core/transport/connectivity_state.c
  60. 3
      src/core/transport/connectivity_state.h
  61. 52
      src/core/transport/transport.c
  62. 22
      src/core/transport/transport.h
  63. 16
      src/core/transport/transport_impl.h
  64. 14
      test/core/bad_client/bad_client.c
  65. 32
      test/core/channel/channel_stack_test.c
  66. 33
      test/core/end2end/fixtures/h2_sockpair+trace.c
  67. 33
      test/core/end2end/fixtures/h2_sockpair.c
  68. 33
      test/core/end2end/fixtures/h2_sockpair_1byte.c
  69. 29
      test/core/httpcli/httpcli_test.c
  70. 63
      test/core/iomgr/alarm_list_test.c
  71. 10
      test/core/iomgr/alarm_test.c
  72. 22
      test/core/iomgr/endpoint_pair_test.c
  73. 3
      test/core/iomgr/endpoint_tests.c
  74. 11
      test/core/iomgr/fd_conservation_posix_test.c
  75. 121
      test/core/iomgr/fd_posix_test.c
  76. 6
      test/core/iomgr/resolve_address_test.c
  77. 69
      test/core/iomgr/tcp_client_posix_test.c
  78. 118
      test/core/security/credentials_test.c
  79. 60
      test/core/security/jwt_verifier_test.c
  80. 2
      test/core/security/oauth2_utils.c
  81. 44
      test/core/security/secure_endpoint_test.c
  82. 21
      test/core/surface/completion_queue_test.c
  83. 4
      test/core/util/port_posix.c
  84. 4
      test/core/util/reconnect_server.c

@ -128,7 +128,8 @@ static void server_start_transport_op(grpc_call_element* elem,
static void client_init_call_elem(grpc_call_element* elem,
const void* server_transport_data,
grpc_transport_stream_op* initial_op) {
grpc_transport_stream_op* initial_op,
grpc_call_list* call_list) {
call_data* d = elem->call_data;
GPR_ASSERT(d != NULL);
d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
@ -144,7 +145,8 @@ static void client_destroy_call_elem(grpc_call_element* elem,
static void server_init_call_elem(grpc_call_element* elem,
const void* server_transport_data,
grpc_transport_stream_op* initial_op) {
grpc_transport_stream_op* initial_op,
grpc_call_list* call_list) {
call_data* d = elem->call_data;
GPR_ASSERT(d != NULL);
d->start_ts = gpr_now(GPR_CLOCK_REALTIME);

@ -153,7 +153,8 @@ void grpc_channel_stack_destroy(grpc_channel_stack *stack,
void grpc_call_stack_init(grpc_channel_stack *channel_stack,
const void *transport_server_data,
grpc_transport_stream_op *initial_op,
grpc_call_stack *call_stack) {
grpc_call_stack *call_stack,
grpc_call_list *call_list) {
grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
size_t count = channel_stack->count;
grpc_call_element *call_elems;
@ -171,7 +172,7 @@ void grpc_call_stack_init(grpc_channel_stack *channel_stack,
call_elems[i].channel_data = channel_elems[i].channel_data;
call_elems[i].call_data = user_data;
call_elems[i].filter->init_call_elem(&call_elems[i], transport_server_data,
initial_op);
initial_op, call_list);
user_data +=
ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
}

@ -85,7 +85,8 @@ typedef struct {
argument.*/
void (*init_call_elem)(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op);
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list);
/* Destroy per call data.
The filter does not need to do any chaining */
void (*destroy_call_elem)(grpc_call_element *elem, grpc_call_list *call_list);
@ -172,7 +173,8 @@ void grpc_channel_stack_destroy(grpc_channel_stack *stack,
void grpc_call_stack_init(grpc_channel_stack *channel_stack,
const void *transport_server_data,
grpc_transport_stream_op *initial_op,
grpc_call_stack *call_stack);
grpc_call_stack *call_stack,
grpc_call_list *call_list);
/* Destroy a call stack */
void grpc_call_stack_destroy(grpc_call_stack *stack, grpc_call_list *call_list);

@ -459,7 +459,7 @@ static void on_lb_policy_state_changed(void *arg, int iomgr_success,
on_lb_policy_state_changed_locked(w, call_list);
gpr_mu_unlock(&w->chand->mu_config);
GRPC_CHANNEL_INTERNAL_UNREF(w->chand->master, "watch_lb_policy");
GRPC_CHANNEL_INTERNAL_UNREF(w->chand->master, "watch_lb_policy", call_list);
gpr_free(w);
}
@ -551,7 +551,7 @@ static void cc_on_config_changed(void *arg, int iomgr_success,
GRPC_LB_POLICY_UNREF(lb_policy, "config_change", call_list);
}
GRPC_CHANNEL_INTERNAL_UNREF(chand->master, "resolver");
GRPC_CHANNEL_INTERNAL_UNREF(chand->master, "resolver", call_list);
}
static void cc_start_transport_op(grpc_channel_element *elem,
@ -610,7 +610,8 @@ static void cc_start_transport_op(grpc_channel_element *elem,
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
call_data *calld = elem->call_data;
/* TODO(ctiller): is there something useful we can do here? */
@ -688,7 +689,7 @@ static void destroy_channel_elem(grpc_channel_element *elem,
if (chand->lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel", call_list);
}
grpc_connectivity_state_destroy(&chand->state_tracker);
grpc_connectivity_state_destroy(&chand->state_tracker, call_list);
grpc_pollset_set_destroy(&chand->pollset_set);
gpr_mu_destroy(&chand->mu_config);
}

@ -282,7 +282,8 @@ static void compress_start_transport_stream_op(grpc_call_element *elem,
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;

@ -69,21 +69,22 @@ static void con_start_transport_stream_op(grpc_call_element *elem,
GPR_ASSERT(elem->filter == &grpc_connected_channel_filter);
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
grpc_transport_perform_stream_op(chand->transport,
TRANSPORT_STREAM_FROM_CALL_DATA(calld), op);
grpc_transport_perform_stream_op(
chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), op, call_list);
}
static void con_start_transport_op(grpc_channel_element *elem,
grpc_transport_op *op,
grpc_call_list *call_list) {
channel_data *chand = elem->channel_data;
grpc_transport_perform_op(chand->transport, op);
grpc_transport_perform_op(chand->transport, op, call_list);
}
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
int r;
@ -91,7 +92,7 @@ static void init_call_elem(grpc_call_element *elem,
GPR_ASSERT(elem->filter == &grpc_connected_channel_filter);
r = grpc_transport_init_stream(chand->transport,
TRANSPORT_STREAM_FROM_CALL_DATA(calld),
server_transport_data, initial_op);
server_transport_data, initial_op, call_list);
GPR_ASSERT(r == 0);
}
@ -101,8 +102,8 @@ static void destroy_call_elem(grpc_call_element *elem,
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
GPR_ASSERT(elem->filter == &grpc_connected_channel_filter);
grpc_transport_destroy_stream(chand->transport,
TRANSPORT_STREAM_FROM_CALL_DATA(calld));
grpc_transport_destroy_stream(
chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), call_list);
}
/* Constructor for channel_data */
@ -121,12 +122,12 @@ static void destroy_channel_elem(grpc_channel_element *elem,
grpc_call_list *call_list) {
channel_data *cd = (channel_data *)elem->channel_data;
GPR_ASSERT(elem->filter == &grpc_connected_channel_filter);
grpc_transport_destroy(cd->transport);
grpc_transport_destroy(cd->transport, call_list);
}
static char *con_get_peer(grpc_call_element *elem, grpc_call_list *call_list) {
channel_data *chand = elem->channel_data;
return grpc_transport_get_peer(chand->transport);
return grpc_transport_get_peer(chand->transport, call_list);
}
const grpc_channel_filter grpc_connected_channel_filter = {

@ -165,7 +165,8 @@ static void hc_start_transport_op(grpc_call_element *elem,
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
call_data *calld = elem->call_data;
calld->sent_initial_metadata = 0;
calld->got_initial_metadata = 0;

@ -238,7 +238,8 @@ static void hs_start_transport_op(grpc_call_element *elem,
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
/* initialize members */

@ -74,7 +74,8 @@ static void noop_start_transport_stream_op(grpc_call_element *elem,
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data;

@ -101,7 +101,7 @@ void pf_destroy(grpc_lb_policy *pol, grpc_call_list *call_list) {
for (i = 0; i < p->num_subchannels; i++) {
GRPC_SUBCHANNEL_UNREF(p->subchannels[i], "pick_first", call_list);
}
grpc_connectivity_state_destroy(&p->state_tracker);
grpc_connectivity_state_destroy(&p->state_tracker, call_list);
gpr_free(p->subchannels);
gpr_mu_destroy(&p->mu);
gpr_free(p);

@ -197,7 +197,7 @@ static void dns_destroy(grpc_resolver *gr, grpc_call_list *call_list) {
if (r->resolved_config) {
grpc_client_config_unref(r->resolved_config, call_list);
}
grpc_subchannel_factory_unref(r->subchannel_factory);
grpc_subchannel_factory_unref(r->subchannel_factory, call_list);
gpr_free(r->name);
gpr_free(r->default_port);
gpr_free(r->lb_policy_name);

@ -159,7 +159,7 @@ static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r,
static void sockaddr_destroy(grpc_resolver *gr, grpc_call_list *call_list) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_subchannel_factory_unref(r->subchannel_factory);
grpc_subchannel_factory_unref(r->subchannel_factory, call_list);
gpr_free(r->addrs);
gpr_free(r->addrs_len);
gpr_free(r->lb_policy_name);

@ -143,7 +143,8 @@ struct grpc_subchannel_call {
#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1))
#define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)((con) + 1))
static grpc_subchannel_call *create_call(connection *con);
static grpc_subchannel_call *create_call(connection *con,
grpc_call_list *call_list);
static void connectivity_state_changed_locked(grpc_subchannel *c,
const char *reason,
grpc_call_list *call_list);
@ -262,7 +263,7 @@ static void subchannel_destroy(grpc_subchannel *c, grpc_call_list *call_list) {
grpc_channel_args_destroy(c->args);
gpr_free(c->addr);
grpc_mdctx_unref(c->mdctx);
grpc_connectivity_state_destroy(&c->state_tracker);
grpc_connectivity_state_destroy(&c->state_tracker, call_list);
grpc_connector_unref(c->connector, call_list);
gpr_free(c);
}
@ -355,7 +356,7 @@ void grpc_subchannel_create_call(grpc_subchannel *c, grpc_pollset *pollset,
CONNECTION_REF_LOCKED(con, "call");
gpr_mu_unlock(&c->mu);
*target = create_call(con);
*target = create_call(con, call_list);
notify->cb(notify->cb_arg, 1, call_list);
} else {
waiting_for_connect *w4c = gpr_malloc(sizeof(*w4c));
@ -561,7 +562,7 @@ static void publish_transport(grpc_subchannel *c, grpc_call_list *call_list) {
gpr_free(sw);
gpr_free(filters);
grpc_channel_stack_destroy(stk, call_list);
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting", call_list);
GRPC_SUBCHANNEL_UNREF(c, "connecting", call_list);
return;
}
@ -582,7 +583,7 @@ static void publish_transport(grpc_subchannel *c, grpc_call_list *call_list) {
op.on_connectivity_state_change = &sw->closure;
op.bind_pollset_set = c->pollset_set;
SUBCHANNEL_REF_LOCKED(c, "state_watcher");
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting", call_list);
GPR_ASSERT(!SUBCHANNEL_UNREF_LOCKED(c, "connecting"));
elem =
grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(c->active), 0);
@ -650,7 +651,7 @@ static void on_alarm(void *arg, int iomgr_success, grpc_call_list *call_list) {
update_reconnect_parameters(c);
continue_connect(c, call_list);
} else {
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting", call_list);
GRPC_SUBCHANNEL_UNREF(c, "connecting", call_list);
}
}
@ -746,13 +747,14 @@ void grpc_subchannel_call_process_op(grpc_subchannel_call *call,
top_elem->filter->start_transport_stream_op(top_elem, op, call_list);
}
grpc_subchannel_call *create_call(connection *con) {
static grpc_subchannel_call *create_call(connection *con,
grpc_call_list *call_list) {
grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
grpc_subchannel_call *call =
gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
call->connection = con;
gpr_ref_init(&call->refs, 1);
grpc_call_stack_init(chanstk, NULL, NULL, callstk);
grpc_call_stack_init(chanstk, NULL, NULL, callstk, call_list);
return call;
}

@ -36,8 +36,10 @@
void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory) {
factory->vtable->ref(factory);
}
void grpc_subchannel_factory_unref(grpc_subchannel_factory *factory) {
factory->vtable->unref(factory);
void grpc_subchannel_factory_unref(grpc_subchannel_factory *factory,
grpc_call_list *call_list) {
factory->vtable->unref(factory, call_list);
}
grpc_subchannel *grpc_subchannel_factory_create_subchannel(

@ -48,14 +48,15 @@ struct grpc_subchannel_factory {
struct grpc_subchannel_factory_vtable {
void (*ref)(grpc_subchannel_factory *factory);
void (*unref)(grpc_subchannel_factory *factory);
void (*unref)(grpc_subchannel_factory *factory, grpc_call_list *call_list);
grpc_subchannel *(*create_subchannel)(grpc_subchannel_factory *factory,
grpc_subchannel_args *args,
grpc_call_list *call_list);
};
void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory);
void grpc_subchannel_factory_unref(grpc_subchannel_factory *factory);
void grpc_subchannel_factory_unref(grpc_subchannel_factory *factory,
grpc_call_list *call_list);
/** Create a new grpc_subchannel */
grpc_subchannel *grpc_subchannel_factory_create_subchannel(

@ -47,10 +47,11 @@ static void merge_args_factory_ref(grpc_subchannel_factory *scf) {
gpr_ref(&f->refs);
}
static void merge_args_factory_unref(grpc_subchannel_factory *scf) {
static void merge_args_factory_unref(grpc_subchannel_factory *scf,
grpc_call_list *call_list) {
merge_args_factory *f = (merge_args_factory *)scf;
if (gpr_unref(&f->refs)) {
grpc_subchannel_factory_unref(f->wrapped);
grpc_subchannel_factory_unref(f->wrapped, call_list);
grpc_channel_args_destroy(f->merge_args);
gpr_free(f);
}

@ -246,7 +246,7 @@ void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset,
grpc_call_list *call_list) {
char *name;
if (g_get_override &&
g_get_override(request, deadline, on_response, user_data)) {
g_get_override(request, deadline, on_response, user_data, call_list)) {
return;
}
gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path);
@ -263,8 +263,9 @@ void grpc_httpcli_post(grpc_httpcli_context *context, grpc_pollset *pollset,
grpc_httpcli_response_cb on_response, void *user_data,
grpc_call_list *call_list) {
char *name;
if (g_post_override && g_post_override(request, body_bytes, body_size,
deadline, on_response, user_data)) {
if (g_post_override &&
g_post_override(request, body_bytes, body_size, deadline, on_response,
user_data, call_list)) {
return;
}
gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->path);

@ -147,13 +147,15 @@ void grpc_httpcli_post(grpc_httpcli_context *context, grpc_pollset *pollset,
typedef int (*grpc_httpcli_get_override)(const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response,
void *user_data);
void *user_data,
grpc_call_list *call_list);
typedef int (*grpc_httpcli_post_override)(const grpc_httpcli_request *request,
const char *body_bytes,
size_t body_size,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response,
void *user_data);
void *user_data,
grpc_call_list *call_list);
void grpc_httpcli_set_override(grpc_httpcli_get_override get,
grpc_httpcli_post_override post);

@ -291,6 +291,7 @@ static size_t pop_alarms(shard_type *shard, gpr_timespec now,
gpr_mu_lock(&shard->mu);
while ((alarm = pop_one(shard, now))) {
grpc_call_list_add(call_list, &alarm->closure, success);
n++;
}
*new_min_deadline = compute_min_deadline(shard);
gpr_mu_unlock(&shard->mu);
@ -332,7 +333,7 @@ static int run_some_expired_alarms(gpr_timespec now, gpr_timespec *next,
gpr_mu_unlock(&g_checker_mu);
}
return n > 0;
return (int)n;
}
int grpc_alarm_check(gpr_timespec now, gpr_timespec *next,

@ -73,9 +73,12 @@ void grpc_pollset_destroy(grpc_pollset *pollset);
grpc_pollset_work, and it is guaranteed that GRPC_POLLSET_MU(pollset) will
not be released by grpc_pollset_work AFTER worker has been destroyed.
Tries not to block past deadline. */
Tries not to block past deadline.
May call grpc_call_list_run on grpc_call_list, without holding the pollset
lock */
void grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec now, gpr_timespec deadline);
gpr_timespec now, gpr_timespec deadline,
grpc_call_list *call_list);
/* Break one polling thread out of polling work for this pollset.
If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers.

@ -174,21 +174,21 @@ static void finish_shutdown(grpc_pollset *pollset, grpc_call_list *call_list) {
}
void grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec now, gpr_timespec deadline) {
gpr_timespec now, gpr_timespec deadline,
grpc_call_list *call_list) {
/* pollset->mu already held */
int added_worker = 0;
int locked = 1;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
/* this must happen before we (potentially) drop pollset->mu */
worker->next = worker->prev = NULL;
/* TODO(ctiller): pool these */
grpc_wakeup_fd_init(&worker->wakeup_fd);
if (!grpc_pollset_has_workers(pollset) &&
!grpc_call_list_empty(pollset->idle_jobs)) {
grpc_call_list_move(&pollset->idle_jobs, &call_list);
grpc_call_list_move(&pollset->idle_jobs, call_list);
goto done;
}
if (grpc_alarm_check(now, &deadline, &call_list)) {
if (grpc_alarm_check(now, &deadline, call_list)) {
goto done;
}
if (pollset->shutting_down) {
@ -212,14 +212,8 @@ void grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker *worker,
pollset->kicked_without_pollers = 0;
}
done:
if (!grpc_call_list_empty(call_list)) {
if (locked) {
gpr_mu_unlock(&pollset->mu);
locked = 0;
}
grpc_call_list_run(&call_list);
}
if (!locked) {
grpc_call_list_run(call_list);
gpr_mu_lock(&pollset->mu);
locked = 1;
}
@ -233,8 +227,8 @@ done:
} else if (!pollset->called_shutdown && pollset->in_flight_cbs == 0) {
pollset->called_shutdown = 1;
gpr_mu_unlock(&pollset->mu);
finish_shutdown(pollset, &call_list);
grpc_call_list_run(&call_list);
finish_shutdown(pollset, call_list);
grpc_call_list_run(call_list);
/* Continuing to access pollset here is safe -- it is the caller's
* responsibility to not destroy when it has outstanding calls to
* grpc_pollset_work.

@ -34,6 +34,7 @@
#ifndef GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H
#define GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H
#include <stddef.h>
#include "src/core/iomgr/iomgr.h"
#define GRPC_MAX_SOCKADDR_SIZE 128

@ -280,7 +280,8 @@ static void auth_start_transport_op(grpc_call_element *elem,
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
call_data *calld = elem->call_data;
calld->creds = NULL;
calld->host = NULL;

@ -123,7 +123,7 @@ static int is_stack_running_on_compute_engine(void) {
while (!detector.is_done) {
grpc_pollset_worker worker;
grpc_pollset_work(&detector.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
gpr_inf_future(GPR_CLOCK_MONOTONIC));
gpr_inf_future(GPR_CLOCK_MONOTONIC), &call_list);
}
gpr_mu_unlock(GRPC_POLLSET_MU(&detector.pollset));

@ -200,7 +200,8 @@ static void auth_start_transport_op(grpc_call_element *elem,
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;

@ -67,6 +67,7 @@ typedef struct grpc_server_secure_state {
gpr_mu mu;
gpr_refcount refcount;
grpc_closure destroy_closure;
grpc_closure *destroy_callback;
} grpc_server_secure_state;
static void state_ref(grpc_server_secure_state *state) {
@ -86,7 +87,8 @@ static void state_unref(grpc_server_secure_state *state) {
}
static void setup_transport(void *statep, grpc_transport *transport,
grpc_mdctx *mdctx, grpc_workqueue *workqueue) {
grpc_mdctx *mdctx, grpc_workqueue *workqueue,
grpc_call_list *call_list) {
static grpc_channel_filter const *extra_filters[] = {
&grpc_server_auth_filter, &grpc_http_server_filter};
grpc_server_secure_state *state = statep;
@ -100,7 +102,7 @@ static void setup_transport(void *statep, grpc_transport *transport,
GPR_ARRAY_SIZE(args_to_add));
grpc_server_setup_transport(state->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx, workqueue,
args_copy);
args_copy, call_list);
grpc_channel_args_destroy(args_copy);
}
@ -142,9 +144,9 @@ static void on_secure_transport_setup_done(void *statep,
workqueue = grpc_workqueue_create(call_list);
transport = grpc_create_chttp2_transport(
grpc_server_get_channel_args(state->server), secure_endpoint, mdctx,
0);
setup_transport(state, transport, mdctx, workqueue);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
0, call_list);
setup_transport(state, transport, mdctx, workqueue, call_list);
grpc_chttp2_transport_start_reading(transport, NULL, 0, call_list);
} else {
/* We need to consume this here, because the server may already have gone
* away. */
@ -185,7 +187,8 @@ static void start(grpc_server *server, void *statep, grpc_pollset **pollsets,
static void destroy_done(void *statep, int success, grpc_call_list *call_list) {
grpc_server_secure_state *state = statep;
grpc_server_listener_destroy_done(state->server);
state->destroy_callback->cb(state->destroy_callback->cb_arg, success,
call_list);
gpr_mu_lock(&state->mu);
while (state->handshaking_tcp_endpoints != NULL) {
grpc_endpoint_shutdown(state->handshaking_tcp_endpoints->tcp_endpoint,
@ -199,12 +202,13 @@ static void destroy_done(void *statep, int success, grpc_call_list *call_list) {
/* Server callback: destroy the tcp listener (so we don't generate further
callbacks) */
static void destroy(grpc_server *server, void *statep,
static void destroy(grpc_server *server, void *statep, grpc_closure *callback,
grpc_call_list *call_list) {
grpc_server_secure_state *state = statep;
grpc_tcp_server *tcp;
gpr_mu_lock(&state->mu);
state->is_shutdown = 1;
state->destroy_callback = callback;
tcp = state->tcp;
gpr_mu_unlock(&state->mu);
grpc_closure_init(&state->destroy_closure, destroy_done, state);
@ -283,7 +287,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
gpr_ref_init(&state->refcount, 1);
/* Register with the server only upon success */
grpc_server_add_listener(server, state, start, destroy);
grpc_server_add_listener(server, state, start, destroy, &call_list);
grpc_call_list_run(&call_list);
return port_num;

@ -356,7 +356,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
initial_op_ptr = &initial_op;
}
grpc_call_stack_init(channel_stack, server_transport_data, initial_op_ptr,
CALL_STACK_FROM_CALL(call));
CALL_STACK_FROM_CALL(call), &call_list);
if (parent_call != NULL) {
GRPC_CALL_INTERNAL_REF(parent_call, "child");
GPR_ASSERT(call->is_client);
@ -459,7 +459,7 @@ static void destroy_call(grpc_call *call, grpc_call_list *call_list) {
size_t i;
grpc_call *c = call;
grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c), call_list);
GRPC_CHANNEL_INTERNAL_UNREF(c->channel, "call");
GRPC_CHANNEL_INTERNAL_UNREF(c->channel, "call", call_list);
gpr_mu_destroy(&c->mu);
gpr_mu_destroy(&c->completion_mu);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
@ -673,7 +673,8 @@ static void unlock(grpc_call *call, grpc_call_list *call_list) {
if (completing_requests > 0) {
for (i = 0; i < completing_requests; i++) {
completed_requests[i].on_complete(call, completed_requests[i].success,
completed_requests[i].user_data);
completed_requests[i].user_data,
call_list);
}
lock(call);
call->completing = 0;
@ -1556,14 +1557,16 @@ static void set_cancelled_value(grpc_status_code status, void *dest) {
*(grpc_status_code *)dest = (status != GRPC_STATUS_OK);
}
static void finish_batch(grpc_call *call, int success, void *tag) {
static void finish_batch(grpc_call *call, int success, void *tag,
grpc_call_list *call_list) {
grpc_cq_end_op(call->cq, tag, success, done_completion, call,
allocate_completion(call));
allocate_completion(call), call_list);
}
static void finish_batch_with_close(grpc_call *call, int success, void *tag) {
static void finish_batch_with_close(grpc_call *call, int success, void *tag,
grpc_call_list *call_list) {
grpc_cq_end_op(call->cq, tag, 1, done_completion, call,
allocate_completion(call));
allocate_completion(call), call_list);
}
static int are_write_flags_valid(gpr_uint32 flags) {
@ -1581,7 +1584,8 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
size_t out;
const grpc_op *op;
grpc_ioreq *req;
void (*finish_func)(grpc_call *, int, void *) = finish_batch;
void (*finish_func)(grpc_call *, int, void *, grpc_call_list *) =
finish_batch;
grpc_call_error error;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
@ -1596,7 +1600,7 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
grpc_cq_begin_op(call->cq);
GRPC_CALL_INTERNAL_REF(call, "completion");
grpc_cq_end_op(call->cq, tag, 1, done_completion, call,
allocate_completion(call));
allocate_completion(call), &call_list);
error = GRPC_CALL_OK;
goto done;
}

@ -87,7 +87,8 @@ typedef struct {
} grpc_ioreq;
typedef void (*grpc_ioreq_completion_func)(grpc_call *call, int success,
void *user_data);
void *user_data,
grpc_call_list *call_list);
grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
gpr_uint32 propagation_mask,

@ -272,9 +272,9 @@ void grpc_channel_internal_ref(grpc_channel *c) {
gpr_ref(&c->refs);
}
static void destroy_channel(grpc_channel *channel) {
static void destroy_channel(grpc_channel *channel, grpc_call_list *call_list) {
size_t i;
grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel));
grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel), call_list);
for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) {
GRPC_MDELEM_UNREF(channel->grpc_status_elem[i]);
}
@ -303,26 +303,31 @@ static void destroy_channel(grpc_channel *channel) {
}
#ifdef GRPC_CHANNEL_REF_COUNT_DEBUG
void grpc_channel_internal_unref(grpc_channel *channel, const char *reason) {
void grpc_channel_internal_unref(grpc_channel *channel, const char *reason,
grpc_call_list *call_list) {
gpr_log(GPR_DEBUG, "CHANNEL: unref %p %d -> %d [%s]", channel,
channel->refs.count, channel->refs.count - 1, reason);
#else
void grpc_channel_internal_unref(grpc_channel *channel) {
void grpc_channel_internal_unref(grpc_channel *channel,
grpc_call_list *call_list) {
#endif
if (gpr_unref(&channel->refs)) {
destroy_channel(channel);
destroy_channel(channel, call_list);
}
}
void grpc_channel_destroy(grpc_channel *channel) {
grpc_transport_op op;
grpc_channel_element *elem;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
memset(&op, 0, sizeof(op));
op.disconnect = 1;
elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
elem->filter->start_transport_op(elem, &op);
elem->filter->start_transport_op(elem, &op, &call_list);
GRPC_CHANNEL_INTERNAL_UNREF(channel, "channel");
GRPC_CHANNEL_INTERNAL_UNREF(channel, "channel", &call_list);
grpc_call_list_run(&call_list);
}
grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel) {

@ -67,18 +67,20 @@ grpc_workqueue *grpc_channel_get_workqueue(grpc_channel *channel);
#ifdef GRPC_CHANNEL_REF_COUNT_DEBUG
void grpc_channel_internal_ref(grpc_channel *channel, const char *reason);
void grpc_channel_internal_unref(grpc_channel *channel, const char *reason);
void grpc_channel_internal_unref(grpc_channel *channel, const char *reason,
grpc_call_list *call_list);
#define GRPC_CHANNEL_INTERNAL_REF(channel, reason) \
grpc_channel_internal_ref(channel, reason)
#define GRPC_CHANNEL_INTERNAL_UNREF(channel, reason) \
grpc_channel_internal_unref(channel, reason)
#define GRPC_CHANNEL_INTERNAL_UNREF(channel, reason, call_list) \
grpc_channel_internal_unref(channel, reason, call_list)
#else
void grpc_channel_internal_ref(grpc_channel *channel);
void grpc_channel_internal_unref(grpc_channel *channel);
void grpc_channel_internal_unref(grpc_channel *channel,
grpc_call_list *call_list);
#define GRPC_CHANNEL_INTERNAL_REF(channel, reason) \
grpc_channel_internal_ref(channel)
#define GRPC_CHANNEL_INTERNAL_UNREF(channel, reason) \
grpc_channel_internal_unref(channel)
#define GRPC_CHANNEL_INTERNAL_UNREF(channel, reason, call_list) \
grpc_channel_internal_unref(channel, call_list)
#endif
#endif /* GRPC_INTERNAL_CORE_SURFACE_CHANNEL_H */

@ -56,7 +56,7 @@ grpc_connectivity_state grpc_channel_check_connectivity_state(
}
state = grpc_client_channel_check_connectivity_state(
client_channel_elem, try_to_connect, &call_list);
grpc_call_list_run(call_list);
grpc_call_list_run(&call_list);
return state;
}
@ -80,17 +80,18 @@ typedef struct {
void *tag;
} state_watcher;
static void delete_state_watcher(state_watcher *w) {
static void delete_state_watcher(state_watcher *w, grpc_call_list *call_list) {
grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(
grpc_channel_get_channel_stack(w->channel));
grpc_client_channel_del_interested_party(client_channel_elem,
grpc_cq_pollset(w->cq));
GRPC_CHANNEL_INTERNAL_UNREF(w->channel, "watch_connectivity");
grpc_cq_pollset(w->cq), call_list);
GRPC_CHANNEL_INTERNAL_UNREF(w->channel, "watch_connectivity", call_list);
gpr_mu_destroy(&w->mu);
gpr_free(w);
}
static void finished_completion(void *pw, grpc_cq_completion *ignored) {
static void finished_completion(void *pw, grpc_cq_completion *ignored,
grpc_call_list *call_list) {
int delete = 0;
state_watcher *w = pw;
gpr_mu_lock(&w->mu);
@ -110,18 +111,19 @@ static void finished_completion(void *pw, grpc_cq_completion *ignored) {
gpr_mu_unlock(&w->mu);
if (delete) {
delete_state_watcher(w);
delete_state_watcher(w, call_list);
}
}
static void partly_done(state_watcher *w, int due_to_completion) {
static void partly_done(state_watcher *w, int due_to_completion,
grpc_call_list *call_list) {
int delete = 0;
if (due_to_completion) {
gpr_mu_lock(&w->mu);
w->success = 1;
gpr_mu_unlock(&w->mu);
grpc_alarm_cancel(&w->alarm);
grpc_alarm_cancel(&w->alarm, call_list);
}
gpr_mu_lock(&w->mu);
@ -129,7 +131,7 @@ static void partly_done(state_watcher *w, int due_to_completion) {
case WAITING:
w->phase = CALLING_BACK;
grpc_cq_end_op(w->cq, w->tag, w->success, finished_completion, w,
&w->completion_storage);
&w->completion_storage, call_list);
break;
case CALLING_BACK:
w->phase = CALLING_BACK_AND_FINISHED;
@ -145,13 +147,17 @@ static void partly_done(state_watcher *w, int due_to_completion) {
gpr_mu_unlock(&w->mu);
if (delete) {
delete_state_watcher(w);
delete_state_watcher(w, call_list);
}
}
static void watch_complete(void *pw, int success) { partly_done(pw, 1); }
static void watch_complete(void *pw, int success, grpc_call_list *call_list) {
partly_done(pw, 1, call_list);
}
static void timeout_complete(void *pw, int success) { partly_done(pw, 0); }
static void timeout_complete(void *pw, int success, grpc_call_list *call_list) {
partly_done(pw, 0, call_list);
}
void grpc_channel_watch_connectivity_state(
grpc_channel *channel, grpc_connectivity_state last_observed_state,
@ -172,9 +178,9 @@ void grpc_channel_watch_connectivity_state(
w->tag = tag;
w->channel = channel;
grpc_alarm_init(&w->alarm,
gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
timeout_complete, w, gpr_now(GPR_CLOCK_MONOTONIC));
grpc_alarm_init(
&w->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
timeout_complete, w, gpr_now(GPR_CLOCK_MONOTONIC), &call_list);
if (client_channel_elem->filter != &grpc_client_channel_filter) {
gpr_log(GPR_ERROR,
@ -185,10 +191,10 @@ void grpc_channel_watch_connectivity_state(
} else {
GRPC_CHANNEL_INTERNAL_REF(channel, "watch_connectivity");
grpc_client_channel_add_interested_party(client_channel_elem,
grpc_cq_pollset(cq));
grpc_cq_pollset(cq), &call_list);
grpc_client_channel_watch_connectivity_state(client_channel_elem, &w->state,
&w->on_complete, &call_list);
}
grpc_call_list_run(call_list);
grpc_call_list_run(&call_list);
}

@ -55,6 +55,13 @@ typedef struct {
grpc_closure *notify;
grpc_connect_in_args args;
grpc_connect_out_args *result;
grpc_endpoint *tcp;
grpc_mdctx *mdctx;
grpc_workqueue *workqueue;
grpc_closure connected;
} connector;
static void connector_ref(grpc_connector *con) {
@ -62,21 +69,24 @@ static void connector_ref(grpc_connector *con) {
gpr_ref(&c->refs);
}
static void connector_unref(grpc_connector *con) {
static void connector_unref(grpc_connector *con, grpc_call_list *call_list) {
connector *c = (connector *)con;
if (gpr_unref(&c->refs)) {
grpc_mdctx_unref(c->mdctx);
GRPC_WORKQUEUE_UNREF(c->workqueue, "connector", call_list);
gpr_free(c);
}
}
static void connected(void *arg, grpc_endpoint *tcp) {
static void connected(void *arg, int success, grpc_call_list *call_list) {
connector *c = arg;
grpc_closure *notify;
grpc_endpoint *tcp = c->tcp;
if (tcp != NULL) {
c->result->transport = grpc_create_chttp2_transport(
c->args.channel_args, tcp, c->args.metadata_context, c->args.workqueue,
1);
grpc_chttp2_transport_start_reading(c->result->transport, NULL, 0);
c->args.channel_args, tcp, c->mdctx, 1, call_list);
grpc_chttp2_transport_start_reading(c->result->transport, NULL, 0,
call_list);
GPR_ASSERT(c->result->transport);
c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *));
c->result->filters[0] = &grpc_http_client_filter;
@ -86,24 +96,27 @@ static void connected(void *arg, grpc_endpoint *tcp) {
}
notify = c->notify;
c->notify = NULL;
notify->cb(notify->cb_arg, 1);
notify->cb(notify->cb_arg, 1, call_list);
}
static void connector_shutdown(grpc_connector *con) {}
static void connector_shutdown(grpc_connector *con, grpc_call_list *call_list) {
}
static void connector_connect(grpc_connector *con,
const grpc_connect_in_args *args,
grpc_connect_out_args *result,
grpc_closure *notify) {
grpc_closure *notify, grpc_call_list *call_list) {
connector *c = (connector *)con;
GPR_ASSERT(c->notify == NULL);
GPR_ASSERT(notify->cb);
c->notify = notify;
c->args = *args;
c->result = result;
grpc_tcp_client_connect(connected, c, args->interested_parties,
args->workqueue, args->addr, args->addr_len,
args->deadline);
c->tcp = NULL;
grpc_closure_init(&c->connected, connected, c);
grpc_tcp_client_connect(&c->connected, &c->tcp, args->interested_parties,
args->addr, args->addr_len, args->deadline,
call_list);
}
static const grpc_connector_vtable connector_vtable = {
@ -122,10 +135,11 @@ static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
gpr_ref(&f->refs);
}
static void subchannel_factory_unref(grpc_subchannel_factory *scf) {
static void subchannel_factory_unref(grpc_subchannel_factory *scf,
grpc_call_list *call_list) {
subchannel_factory *f = (subchannel_factory *)scf;
if (gpr_unref(&f->refs)) {
GRPC_CHANNEL_INTERNAL_UNREF(f->master, "subchannel_factory");
GRPC_CHANNEL_INTERNAL_UNREF(f->master, "subchannel_factory", call_list);
grpc_channel_args_destroy(f->merge_args);
grpc_mdctx_unref(f->mdctx);
gpr_free(f);
@ -133,7 +147,8 @@ static void subchannel_factory_unref(grpc_subchannel_factory *scf) {
}
static grpc_subchannel *subchannel_factory_create_subchannel(
grpc_subchannel_factory *scf, grpc_subchannel_args *args) {
grpc_subchannel_factory *scf, grpc_subchannel_args *args,
grpc_call_list *call_list) {
subchannel_factory *f = (subchannel_factory *)scf;
connector *c = gpr_malloc(sizeof(*c));
grpc_channel_args *final_args =
@ -146,7 +161,7 @@ static grpc_subchannel *subchannel_factory_create_subchannel(
args->args = final_args;
args->master = f->master;
s = grpc_subchannel_create(&c->base, args);
grpc_connector_unref(&c->base);
grpc_connector_unref(&c->base, call_list);
grpc_channel_args_destroy(final_args);
return s;
}
@ -168,7 +183,8 @@ grpc_channel *grpc_insecure_channel_create(const char *target,
grpc_resolver *resolver;
subchannel_factory *f;
grpc_mdctx *mdctx = grpc_mdctx_create();
grpc_workqueue *workqueue = grpc_workqueue_create();
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_workqueue *workqueue = grpc_workqueue_create(&call_list);
size_t n = 0;
GPR_ASSERT(!reserved);
if (grpc_channel_args_is_census_enabled(args)) {
@ -179,7 +195,7 @@ grpc_channel *grpc_insecure_channel_create(const char *target,
GPR_ASSERT(n <= MAX_FILTERS);
channel = grpc_channel_create_from_filters(target, filters, n, args, mdctx,
workqueue, 1);
workqueue, 1, &call_list);
f = gpr_malloc(sizeof(*f));
f->base.vtable = &subchannel_factory_vtable;
@ -189,15 +205,17 @@ grpc_channel *grpc_insecure_channel_create(const char *target,
f->merge_args = grpc_channel_args_copy(args);
f->master = channel;
GRPC_CHANNEL_INTERNAL_REF(f->master, "subchannel_factory");
resolver = grpc_resolver_create(target, &f->base, workqueue);
resolver = grpc_resolver_create(target, &f->base);
if (!resolver) {
return NULL;
}
grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel),
resolver);
GRPC_RESOLVER_UNREF(resolver, "create");
grpc_subchannel_factory_unref(&f->base);
resolver, &call_list);
GRPC_RESOLVER_UNREF(resolver, "create", &call_list);
grpc_subchannel_factory_unref(&f->base, &call_list);
grpc_call_list_run(&call_list);
return channel;
}

@ -67,8 +67,12 @@ struct grpc_completion_queue {
int is_server_cq;
int num_pluckers;
plucker pluckers[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS];
grpc_closure pollset_destroy_done;
};
static void on_pollset_destroy_done(void *cc, int success,
grpc_call_list *call_list);
grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
grpc_completion_queue *cc = gpr_malloc(sizeof(grpc_completion_queue));
GPR_ASSERT(!reserved);
@ -80,6 +84,7 @@ grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
grpc_pollset_init(&cc->pollset);
cc->completed_tail = &cc->completed_head;
cc->completed_head.next = (gpr_uintptr)cc->completed_tail;
grpc_closure_init(&cc->pollset_destroy_done, on_pollset_destroy_done, cc);
return cc;
}
@ -94,7 +99,8 @@ void grpc_cq_internal_ref(grpc_completion_queue *cc) {
gpr_ref(&cc->owning_refs);
}
static void on_pollset_destroy_done(void *arg) {
static void on_pollset_destroy_done(void *arg, int success,
grpc_call_list *call_list) {
grpc_completion_queue *cc = arg;
GRPC_CQ_INTERNAL_UNREF(cc, "pollset_destroy");
}
@ -127,8 +133,10 @@ void grpc_cq_begin_op(grpc_completion_queue *cc) {
event, then enter shutdown mode */
/* Queue a GRPC_OP_COMPLETED operation */
void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, int success,
void (*done)(void *done_arg, grpc_cq_completion *storage),
void *done_arg, grpc_cq_completion *storage) {
void (*done)(void *done_arg, grpc_cq_completion *storage,
grpc_call_list *call_list),
void *done_arg, grpc_cq_completion *storage,
grpc_call_list *call_list) {
int shutdown;
int i;
grpc_pollset_worker *pluck_worker;
@ -162,7 +170,7 @@ void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, int success,
GPR_ASSERT(cc->shutdown_called);
cc->shutdown = 1;
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
grpc_pollset_shutdown(&cc->pollset, &cc->pollset_destroy_done, call_list);
}
}
@ -172,6 +180,7 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
grpc_pollset_worker worker;
int first_loop = 1;
gpr_timespec now;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
GPR_ASSERT(!reserved);
@ -190,7 +199,7 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
ret.type = GRPC_OP_COMPLETE;
ret.success = c->next & 1u;
ret.tag = c->tag;
c->done(c->done_arg, c);
c->done(c->done_arg, c, &call_list);
break;
}
if (cc->shutdown) {
@ -207,10 +216,11 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
break;
}
first_loop = 0;
grpc_pollset_work(&cc->pollset, &worker, now, deadline);
grpc_pollset_work(&cc->pollset, &worker, now, deadline, &call_list);
}
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
GRPC_CQ_INTERNAL_UNREF(cc, "next");
grpc_call_list_run(&call_list);
return ret;
}
@ -247,6 +257,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
grpc_pollset_worker worker;
gpr_timespec now;
int first_loop = 1;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
GPR_ASSERT(!reserved);
@ -268,7 +279,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
ret.type = GRPC_OP_COMPLETE;
ret.success = c->next & 1u;
ret.tag = c->tag;
c->done(c->done_arg, c);
c->done(c->done_arg, c, &call_list);
goto done;
}
prev = c;
@ -299,18 +310,20 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
break;
}
first_loop = 0;
grpc_pollset_work(&cc->pollset, &worker, now, deadline);
grpc_pollset_work(&cc->pollset, &worker, now, deadline, &call_list);
del_plucker(cc, tag, &worker);
}
done:
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
grpc_call_list_run(&call_list);
return ret;
}
/* Shutdown simply drops a ref that we reserved at creation time; if we drop
to zero here, then enter shutdown mode and wake up any waiters */
void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
if (cc->shutdown_called) {
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
@ -324,8 +337,9 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
GPR_ASSERT(!cc->shutdown);
cc->shutdown = 1;
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
grpc_pollset_shutdown(&cc->pollset, &cc->pollset_destroy_done, &call_list);
}
grpc_call_list_run(&call_list);
}
void grpc_completion_queue_destroy(grpc_completion_queue *cc) {

@ -44,7 +44,8 @@ typedef struct grpc_cq_completion {
void *tag;
/** done callback - called when this queue element is no longer
needed by the completion queue */
void (*done)(void *done_arg, struct grpc_cq_completion *c);
void (*done)(void *done_arg, struct grpc_cq_completion *c,
grpc_call_list *call_list);
void *done_arg;
/** next pointer; low bit is used to indicate success or not */
gpr_uintptr next;
@ -74,7 +75,8 @@ void grpc_cq_begin_op(grpc_completion_queue *cc);
void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, int success,
void (*done)(void *done_arg, grpc_cq_completion *storage,
grpc_call_list *call_list),
void *done_arg, grpc_cq_completion *storage);
void *done_arg, grpc_cq_completion *storage,
grpc_call_list *call_list);
grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc);

@ -55,13 +55,14 @@ typedef struct {
} channel_data;
static void lame_start_transport_stream_op(grpc_call_element *elem,
grpc_transport_stream_op *op) {
grpc_transport_stream_op *op,
grpc_call_list *call_list) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
if (op->send_ops != NULL) {
grpc_stream_ops_unref_owned_objects(op->send_ops->ops, op->send_ops->nops);
op->on_done_send->cb(op->on_done_send->cb_arg, 0);
op->on_done_send->cb(op->on_done_send->cb_arg, 0, call_list);
}
if (op->recv_ops != NULL) {
char tmp[GPR_LTOA_MIN_BUFSIZE];
@ -80,44 +81,48 @@ static void lame_start_transport_stream_op(grpc_call_element *elem,
mdb.deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
grpc_sopb_add_metadata(op->recv_ops, mdb);
*op->recv_state = GRPC_STREAM_CLOSED;
op->on_done_recv->cb(op->on_done_recv->cb_arg, 1);
op->on_done_recv->cb(op->on_done_recv->cb_arg, 1, call_list);
}
if (op->on_consumed != NULL) {
op->on_consumed->cb(op->on_consumed->cb_arg, 0);
op->on_consumed->cb(op->on_consumed->cb_arg, 0, call_list);
}
}
static char *lame_get_peer(grpc_call_element *elem) {
static char *lame_get_peer(grpc_call_element *elem, grpc_call_list *call_list) {
channel_data *chand = elem->channel_data;
return grpc_channel_get_target(chand->master);
}
static void lame_start_transport_op(grpc_channel_element *elem,
grpc_transport_op *op) {
grpc_transport_op *op,
grpc_call_list *call_list) {
if (op->on_connectivity_state_change) {
GPR_ASSERT(*op->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE);
*op->connectivity_state = GRPC_CHANNEL_FATAL_FAILURE;
op->on_connectivity_state_change->cb(
op->on_connectivity_state_change->cb_arg, 1);
op->on_connectivity_state_change->cb_arg, 1, call_list);
}
if (op->on_consumed != NULL) {
op->on_consumed->cb(op->on_consumed->cb_arg, 1);
op->on_consumed->cb(op->on_consumed->cb_arg, 1, call_list);
}
}
static void init_call_elem(grpc_call_element *elem,
const void *transport_server_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
if (initial_op) {
grpc_transport_stream_op_finish_with_failure(initial_op);
grpc_transport_stream_op_finish_with_failure(initial_op, call_list);
}
}
static void destroy_call_elem(grpc_call_element *elem) {}
static void destroy_call_elem(grpc_call_element *elem,
grpc_call_list *call_list) {}
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
int is_first, int is_last,
grpc_call_list *call_list) {
channel_data *chand = elem->channel_data;
GPR_ASSERT(is_first);
GPR_ASSERT(is_last);
@ -125,7 +130,8 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
chand->master = master;
}
static void destroy_channel_elem(grpc_channel_element *elem) {}
static void destroy_channel_elem(grpc_channel_element *elem,
grpc_call_list *call_list) {}
static const grpc_channel_filter lame_filter = {
lame_start_transport_stream_op,
@ -148,14 +154,16 @@ grpc_channel *grpc_lame_client_channel_create(const char *target,
grpc_channel *channel;
grpc_channel_element *elem;
channel_data *chand;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
static const grpc_channel_filter *filters[] = {&lame_filter};
channel = grpc_channel_create_from_filters(target, filters, 1, NULL,
grpc_mdctx_create(),
grpc_workqueue_create(), 1);
channel = grpc_channel_create_from_filters(
target, filters, 1, NULL, grpc_mdctx_create(),
grpc_workqueue_create(&call_list), 1, &call_list);
elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
GPR_ASSERT(elem->filter == &lame_filter);
chand = (channel_data *)elem->channel_data;
chand->error_code = error_code;
chand->error_message = error_message;
grpc_call_list_run(&call_list);
return channel;
}

@ -108,8 +108,9 @@ static void on_secure_transport_setup_done(void *arg,
c->connecting_endpoint = NULL;
gpr_mu_unlock(&c->mu);
c->result->transport = grpc_create_chttp2_transport(
c->args.channel_args, secure_endpoint, c->mdctx, 1);
grpc_chttp2_transport_start_reading(c->result->transport, NULL, 0);
c->args.channel_args, secure_endpoint, c->mdctx, 1, call_list);
grpc_chttp2_transport_start_reading(c->result->transport, NULL, 0,
call_list);
c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *) * 2);
c->result->filters[0] = &grpc_http_client_filter;
c->result->filters[1] = &grpc_client_auth_filter;
@ -187,12 +188,13 @@ static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
gpr_ref(&f->refs);
}
static void subchannel_factory_unref(grpc_subchannel_factory *scf) {
static void subchannel_factory_unref(grpc_subchannel_factory *scf,
grpc_call_list *call_list) {
subchannel_factory *f = (subchannel_factory *)scf;
if (gpr_unref(&f->refs)) {
GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
"subchannel_factory");
GRPC_CHANNEL_INTERNAL_UNREF(f->master, "subchannel_factory");
GRPC_CHANNEL_INTERNAL_UNREF(f->master, "subchannel_factory", call_list);
grpc_channel_args_destroy(f->merge_args);
grpc_mdctx_unref(f->mdctx);
gpr_free(f);
@ -279,7 +281,7 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
GPR_ASSERT(n <= MAX_FILTERS);
channel = grpc_channel_create_from_filters(target, filters, n, args_copy,
mdctx, workqueue, 1);
mdctx, workqueue, 1, &call_list);
f = gpr_malloc(sizeof(*f));
f->base.vtable = &subchannel_factory_vtable;
@ -299,7 +301,7 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel),
resolver, &call_list);
GRPC_RESOLVER_UNREF(resolver, "create", &call_list);
grpc_subchannel_factory_unref(&f->base);
grpc_subchannel_factory_unref(&f->base, &call_list);
GRPC_SECURITY_CONNECTOR_UNREF(&connector->base, "channel_create");
grpc_channel_args_destroy(args_copy);

@ -57,9 +57,11 @@
typedef struct listener {
void *arg;
void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
size_t pollset_count);
void (*destroy)(grpc_server *server, void *arg);
size_t pollset_count, grpc_call_list *call_list);
void (*destroy)(grpc_server *server, void *arg, grpc_closure *closure,
grpc_call_list *call_list);
struct listener *next;
grpc_closure destroy_done;
} listener;
typedef struct call_data call_data;
@ -219,19 +221,19 @@ struct grpc_server {
/** when did we print the last shutdown progress message */
gpr_timespec last_shutdown_message_time;
grpc_workqueue *workqueue;
};
#define SERVER_FROM_CALL_ELEM(elem) \
(((channel_data *)(elem)->channel_data)->server)
static void begin_call(grpc_server *server, call_data *calld,
requested_call *rc);
static void fail_call(grpc_server *server, requested_call *rc);
requested_call *rc, grpc_call_list *call_list);
static void fail_call(grpc_server *server, requested_call *rc,
grpc_call_list *call_list);
/* Before calling maybe_finish_shutdown, we must hold mu_global and not
hold mu_call */
static void maybe_finish_shutdown(grpc_server *server);
static void maybe_finish_shutdown(grpc_server *server,
grpc_call_list *call_list);
/*
* channel broadcaster
@ -258,14 +260,15 @@ struct shutdown_cleanup_args {
gpr_slice slice;
};
static void shutdown_cleanup(void *arg, int iomgr_status_ignored) {
static void shutdown_cleanup(void *arg, int iomgr_status_ignored,
grpc_call_list *call_list) {
struct shutdown_cleanup_args *a = arg;
gpr_slice_unref(a->slice);
gpr_free(a);
}
static void send_shutdown(grpc_channel *channel, int send_goaway,
int send_disconnect) {
int send_disconnect, grpc_call_list *call_list) {
grpc_transport_op op;
struct shutdown_cleanup_args *sc;
grpc_channel_element *elem;
@ -281,17 +284,17 @@ static void send_shutdown(grpc_channel *channel, int send_goaway,
op.on_consumed = &sc->closure;
elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
elem->filter->start_transport_op(elem, &op);
elem->filter->start_transport_op(elem, &op, call_list);
}
static void channel_broadcaster_shutdown(channel_broadcaster *cb,
int send_goaway,
int force_disconnect) {
int send_goaway, int force_disconnect,
grpc_call_list *call_list) {
size_t i;
for (i = 0; i < cb->num_channels; i++) {
send_shutdown(cb->channels[i], send_goaway, force_disconnect);
GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast");
send_shutdown(cb->channels[i], send_goaway, force_disconnect, call_list);
GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast", call_list);
}
gpr_free(cb->channels);
}
@ -311,12 +314,12 @@ static void request_matcher_destroy(request_matcher *request_matcher) {
gpr_stack_lockfree_destroy(request_matcher->requests);
}
static void kill_zombie(void *elem, int success) {
static void kill_zombie(void *elem, int success, grpc_call_list *call_list) {
grpc_call_destroy(grpc_call_from_top_element(elem));
}
static void request_matcher_zombify_all_pending_calls(
request_matcher *request_matcher, grpc_workqueue *workqueue) {
request_matcher *request_matcher, grpc_call_list *call_list) {
while (request_matcher->pending_head) {
call_data *calld = request_matcher->pending_head;
request_matcher->pending_head = calld->pending_next;
@ -326,15 +329,16 @@ static void request_matcher_zombify_all_pending_calls(
grpc_closure_init(
&calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
grpc_workqueue_push(workqueue, &calld->kill_zombie_closure, 1);
grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
}
}
static void request_matcher_kill_requests(grpc_server *server,
request_matcher *rm) {
request_matcher *rm,
grpc_call_list *call_list) {
int request_id;
while ((request_id = gpr_stack_lockfree_pop(rm->requests)) != -1) {
fail_call(server, &server->requested_calls[request_id]);
fail_call(server, &server->requested_calls[request_id], call_list);
}
}
@ -346,7 +350,7 @@ static void server_ref(grpc_server *server) {
gpr_ref(&server->internal_refcount);
}
static void server_delete(grpc_server *server) {
static void server_delete(grpc_server *server, grpc_call_list *call_list) {
registered_method *rm;
size_t i;
grpc_channel_args_destroy(server->channel_args);
@ -365,7 +369,6 @@ static void server_delete(grpc_server *server) {
}
request_matcher_destroy(&server->unregistered_request_matcher);
gpr_stack_lockfree_destroy(server->request_freelist);
GRPC_WORKQUEUE_UNREF(server->workqueue, "destroy");
gpr_free(server->cqs);
gpr_free(server->pollsets);
gpr_free(server->shutdown_tags);
@ -373,9 +376,9 @@ static void server_delete(grpc_server *server) {
gpr_free(server);
}
static void server_unref(grpc_server *server) {
static void server_unref(grpc_server *server, grpc_call_list *call_list) {
if (gpr_unref(&server->internal_refcount)) {
server_delete(server);
server_delete(server, call_list);
}
}
@ -389,30 +392,29 @@ static void orphan_channel(channel_data *chand) {
chand->next = chand->prev = chand;
}
static void finish_destroy_channel(void *cd, int success) {
static void finish_destroy_channel(void *cd, int success,
grpc_call_list *call_list) {
channel_data *chand = cd;
grpc_server *server = chand->server;
gpr_log(GPR_DEBUG, "finish_destroy_channel: %p", chand->channel);
GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server");
server_unref(server);
GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server", call_list);
server_unref(server, call_list);
}
static void destroy_channel(channel_data *chand) {
static void destroy_channel(channel_data *chand, grpc_call_list *call_list) {
if (is_channel_orphaned(chand)) return;
GPR_ASSERT(chand->server != NULL);
orphan_channel(chand);
server_ref(chand->server);
maybe_finish_shutdown(chand->server);
maybe_finish_shutdown(chand->server, call_list);
chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
chand->finish_destroy_channel_closure.cb_arg = chand;
gpr_log(GPR_DEBUG, "queue finish_destroy_channel: %p on %p", chand->channel,
chand->server->workqueue);
grpc_workqueue_push(chand->server->workqueue,
&chand->finish_destroy_channel_closure, 1);
grpc_call_list_add(call_list, &chand->finish_destroy_channel_closure, 1);
}
static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
request_matcher *request_matcher) {
request_matcher *request_matcher,
grpc_call_list *call_list) {
call_data *calld = elem->call_data;
int request_id;
@ -421,7 +423,7 @@ static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_workqueue_push(server->workqueue, &calld->kill_zombie_closure, 1);
grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
return;
}
@ -443,11 +445,11 @@ static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
gpr_mu_lock(&calld->mu_state);
calld->state = ACTIVATED;
gpr_mu_unlock(&calld->mu_state);
begin_call(server, calld, &server->requested_calls[request_id]);
begin_call(server, calld, &server->requested_calls[request_id], call_list);
}
}
static void start_new_rpc(grpc_call_element *elem) {
static void start_new_rpc(grpc_call_element *elem, grpc_call_list *call_list) {
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
grpc_server *server = chand->server;
@ -466,7 +468,8 @@ static void start_new_rpc(grpc_call_element *elem) {
if (rm->host != calld->host) continue;
if (rm->method != calld->path) continue;
finish_start_new_rpc(server, elem,
&rm->server_registered_method->request_matcher);
&rm->server_registered_method->request_matcher,
call_list);
return;
}
/* check for a wildcard method definition (no host set) */
@ -478,11 +481,13 @@ static void start_new_rpc(grpc_call_element *elem) {
if (rm->host != NULL) continue;
if (rm->method != calld->path) continue;
finish_start_new_rpc(server, elem,
&rm->server_registered_method->request_matcher);
&rm->server_registered_method->request_matcher,
call_list);
return;
}
}
finish_start_new_rpc(server, elem, &server->unregistered_request_matcher);
finish_start_new_rpc(server, elem, &server->unregistered_request_matcher,
call_list);
}
static int num_listeners(grpc_server *server) {
@ -494,8 +499,9 @@ static int num_listeners(grpc_server *server) {
return n;
}
static void done_shutdown_event(void *server, grpc_cq_completion *completion) {
server_unref(server);
static void done_shutdown_event(void *server, grpc_cq_completion *completion,
grpc_call_list *call_list) {
server_unref(server, call_list);
}
static int num_channels(grpc_server *server) {
@ -508,25 +514,27 @@ static int num_channels(grpc_server *server) {
return n;
}
static void kill_pending_work_locked(grpc_server *server) {
static void kill_pending_work_locked(grpc_server *server,
grpc_call_list *call_list) {
registered_method *rm;
request_matcher_kill_requests(server, &server->unregistered_request_matcher);
request_matcher_kill_requests(server, &server->unregistered_request_matcher,
call_list);
request_matcher_zombify_all_pending_calls(
&server->unregistered_request_matcher, server->workqueue);
&server->unregistered_request_matcher, call_list);
for (rm = server->registered_methods; rm; rm = rm->next) {
request_matcher_kill_requests(server, &rm->request_matcher);
request_matcher_zombify_all_pending_calls(&rm->request_matcher,
server->workqueue);
request_matcher_kill_requests(server, &rm->request_matcher, call_list);
request_matcher_zombify_all_pending_calls(&rm->request_matcher, call_list);
}
}
static void maybe_finish_shutdown(grpc_server *server) {
static void maybe_finish_shutdown(grpc_server *server,
grpc_call_list *call_list) {
size_t i;
if (!gpr_atm_acq_load(&server->shutdown_flag) || server->shutdown_published) {
return;
}
kill_pending_work_locked(server);
kill_pending_work_locked(server, call_list);
if (server->root_channel_data.next != &server->root_channel_data ||
server->listeners_destroyed < num_listeners(server)) {
@ -548,7 +556,7 @@ static void maybe_finish_shutdown(grpc_server *server) {
server_ref(server);
grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, 1,
done_shutdown_event, server,
&server->shutdown_tags[i].completion);
&server->shutdown_tags[i].completion, call_list);
}
}
@ -566,10 +574,9 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
return md;
}
static void server_on_recv(void *ptr, int success) {
static void server_on_recv(void *ptr, int success, grpc_call_list *call_list) {
grpc_call_element *elem = ptr;
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
gpr_timespec op_deadline;
if (success && !calld->got_initial_metadata) {
@ -587,7 +594,7 @@ static void server_on_recv(void *ptr, int success) {
}
if (calld->host && calld->path) {
calld->got_initial_metadata = 1;
start_new_rpc(elem);
start_new_rpc(elem, call_list);
}
break;
}
@ -604,8 +611,7 @@ static void server_on_recv(void *ptr, int success) {
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_workqueue_push(chand->server->workqueue,
&calld->kill_zombie_closure, 1);
grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
} else {
gpr_mu_unlock(&calld->mu_state);
}
@ -616,8 +622,7 @@ static void server_on_recv(void *ptr, int success) {
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_workqueue_push(chand->server->workqueue,
&calld->kill_zombie_closure, 1);
grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
} else if (calld->state == PENDING) {
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
@ -629,7 +634,7 @@ static void server_on_recv(void *ptr, int success) {
break;
}
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success, call_list);
}
static void server_mutate_op(grpc_call_element *elem,
@ -646,10 +651,11 @@ static void server_mutate_op(grpc_call_element *elem,
}
static void server_start_transport_stream_op(grpc_call_element *elem,
grpc_transport_stream_op *op) {
grpc_transport_stream_op *op,
grpc_call_list *call_list) {
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
server_mutate_op(elem, op);
grpc_call_next_op(elem, op);
grpc_call_next_op(elem, op, call_list);
}
static void accept_stream(void *cd, grpc_transport *transport,
@ -660,7 +666,8 @@ static void accept_stream(void *cd, grpc_transport *transport,
0, gpr_inf_future(GPR_CLOCK_MONOTONIC));
}
static void channel_connectivity_changed(void *cd, int iomgr_status_ignored) {
static void channel_connectivity_changed(void *cd, int iomgr_status_ignored,
grpc_call_list *call_list) {
channel_data *chand = cd;
grpc_server *server = chand->server;
if (chand->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
@ -670,18 +677,19 @@ static void channel_connectivity_changed(void *cd, int iomgr_status_ignored) {
op.connectivity_state = &chand->connectivity_state;
grpc_channel_next_op(grpc_channel_stack_element(
grpc_channel_get_channel_stack(chand->channel), 0),
&op);
&op, call_list);
} else {
gpr_mu_lock(&server->mu_global);
destroy_channel(chand);
destroy_channel(chand, call_list);
gpr_mu_unlock(&server->mu_global);
GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "connectivity");
GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "connectivity", call_list);
}
}
static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
memset(calld, 0, sizeof(call_data));
@ -696,7 +704,8 @@ static void init_call_elem(grpc_call_element *elem,
if (initial_op) server_mutate_op(elem, initial_op);
}
static void destroy_call_elem(grpc_call_element *elem) {
static void destroy_call_elem(grpc_call_element *elem,
grpc_call_list *call_list) {
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
@ -711,13 +720,13 @@ static void destroy_call_elem(grpc_call_element *elem) {
gpr_mu_destroy(&calld->mu_state);
server_unref(chand->server);
server_unref(chand->server, call_list);
}
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args,
grpc_mdctx *metadata_context, int is_first,
int is_last) {
int is_last, grpc_call_list *call_list) {
channel_data *chand = elem->channel_data;
GPR_ASSERT(is_first);
GPR_ASSERT(!is_last);
@ -733,7 +742,8 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
channel_connectivity_changed, chand);
}
static void destroy_channel_elem(grpc_channel_element *elem) {
static void destroy_channel_elem(grpc_channel_element *elem,
grpc_call_list *call_list) {
size_t i;
channel_data *chand = elem->channel_data;
if (chand->registered_methods) {
@ -752,11 +762,11 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
chand->next->prev = chand->prev;
chand->prev->next = chand->next;
chand->next = chand->prev = chand;
maybe_finish_shutdown(chand->server);
maybe_finish_shutdown(chand->server, call_list);
gpr_mu_unlock(&chand->server->mu_global);
GRPC_MDSTR_UNREF(chand->path_key);
GRPC_MDSTR_UNREF(chand->authority_key);
server_unref(chand->server);
server_unref(chand->server, call_list);
}
}
@ -810,7 +820,6 @@ grpc_server *grpc_server_create_from_filters(
gpr_ref_init(&server->internal_refcount, 1);
server->root_channel_data.next = server->root_channel_data.prev =
&server->root_channel_data;
server->workqueue = grpc_workqueue_create();
/* TODO(ctiller): expose a channel_arg for this */
server->max_requested_calls = 32768;
@ -881,23 +890,26 @@ void *grpc_server_register_method(grpc_server *server, const char *method,
void grpc_server_start(grpc_server *server) {
listener *l;
size_t i;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
for (i = 0; i < server->cq_count; i++) {
server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
grpc_workqueue_add_to_pollset(server->workqueue, server->pollsets[i]);
}
for (l = server->listeners; l; l = l->next) {
l->start(server, l->arg, server->pollsets, server->cq_count);
l->start(server, l->arg, server->pollsets, server->cq_count, &call_list);
}
grpc_call_list_run(&call_list);
}
void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
grpc_channel_filter const **extra_filters,
size_t num_extra_filters, grpc_mdctx *mdctx,
grpc_workqueue *workqueue,
const grpc_channel_args *args) {
const grpc_channel_args *args,
grpc_call_list *call_list) {
size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
grpc_channel_filter const **filters =
gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
@ -927,11 +939,11 @@ void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
for (i = 0; i < s->cq_count; i++) {
memset(&op, 0, sizeof(op));
op.bind_pollset = grpc_cq_pollset(s->cqs[i]);
grpc_transport_perform_op(transport, &op);
grpc_transport_perform_op(transport, &op, call_list);
}
channel = grpc_channel_create_from_filters(NULL, filters, num_filters, args,
mdctx, workqueue, 0);
mdctx, workqueue, 0, call_list);
chand = (channel_data *)grpc_channel_stack_element(
grpc_channel_get_channel_stack(channel), 0)
->channel_data;
@ -987,19 +999,30 @@ void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
op.on_connectivity_state_change = &chand->channel_connectivity_changed;
op.connectivity_state = &chand->connectivity_state;
op.disconnect = gpr_atm_acq_load(&s->shutdown_flag) != 0;
grpc_transport_perform_op(transport, &op);
grpc_transport_perform_op(transport, &op, call_list);
}
void done_published_shutdown(void *done_arg, grpc_cq_completion *storage) {
void done_published_shutdown(void *done_arg, grpc_cq_completion *storage,
grpc_call_list *call_list) {
(void) done_arg;
gpr_free(storage);
}
static void listener_destroy_done(void *s, int success,
grpc_call_list *call_list) {
grpc_server *server = s;
gpr_mu_lock(&server->mu_global);
server->listeners_destroyed++;
maybe_finish_shutdown(server, call_list);
gpr_mu_unlock(&server->mu_global);
}
void grpc_server_shutdown_and_notify(grpc_server *server,
grpc_completion_queue *cq, void *tag) {
listener *l;
shutdown_tag *sdt;
channel_broadcaster broadcaster;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
GRPC_SERVER_LOG_SHUTDOWN(GPR_INFO, server, cq, tag);
@ -1008,9 +1031,9 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
grpc_cq_begin_op(cq);
if (server->shutdown_published) {
grpc_cq_end_op(cq, tag, 1, done_published_shutdown, NULL,
gpr_malloc(sizeof(grpc_cq_completion)));
gpr_malloc(sizeof(grpc_cq_completion)), &call_list);
gpr_mu_unlock(&server->mu_global);
return;
goto done;
}
server->shutdown_tags =
gpr_realloc(server->shutdown_tags,
@ -1020,7 +1043,7 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
sdt->cq = cq;
if (gpr_atm_acq_load(&server->shutdown_flag)) {
gpr_mu_unlock(&server->mu_global);
return;
goto done;
}
server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
@ -1029,41 +1052,40 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
/* collect all unregistered then registered calls */
gpr_mu_lock(&server->mu_call);
kill_pending_work_locked(server);
kill_pending_work_locked(server, &call_list);
gpr_mu_unlock(&server->mu_call);
gpr_atm_rel_store(&server->shutdown_flag, 1);
maybe_finish_shutdown(server);
maybe_finish_shutdown(server, &call_list);
gpr_mu_unlock(&server->mu_global);
/* Shutdown listeners */
for (l = server->listeners; l; l = l->next) {
l->destroy(server, l->arg);
grpc_closure_init(&l->destroy_done, listener_destroy_done, server);
l->destroy(server, l->arg, &l->destroy_done, &call_list);
}
channel_broadcaster_shutdown(&broadcaster, 1, 0);
}
channel_broadcaster_shutdown(&broadcaster, 1, 0, &call_list);
void grpc_server_listener_destroy_done(void *s) {
grpc_server *server = s;
gpr_mu_lock(&server->mu_global);
server->listeners_destroyed++;
maybe_finish_shutdown(server);
gpr_mu_unlock(&server->mu_global);
done:
grpc_call_list_run(&call_list);
}
void grpc_server_cancel_all_calls(grpc_server *server) {
channel_broadcaster broadcaster;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_mu_lock(&server->mu_global);
channel_broadcaster_init(server, &broadcaster);
gpr_mu_unlock(&server->mu_global);
channel_broadcaster_shutdown(&broadcaster, 0, 1);
channel_broadcaster_shutdown(&broadcaster, 0, 1, &call_list);
grpc_call_list_run(&call_list);
}
void grpc_server_destroy(grpc_server *server) {
listener *l;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_mu_lock(&server->mu_global);
GPR_ASSERT(gpr_atm_acq_load(&server->shutdown_flag) || !server->listeners);
@ -1077,16 +1099,17 @@ void grpc_server_destroy(grpc_server *server) {
gpr_mu_unlock(&server->mu_global);
grpc_workqueue_flush(server->workqueue);
server_unref(server);
server_unref(server, &call_list);
grpc_call_list_run(&call_list);
}
void grpc_server_add_listener(grpc_server *server, void *arg,
void (*start)(grpc_server *server, void *arg,
grpc_pollset **pollsets,
size_t pollset_count),
void (*destroy)(grpc_server *server, void *arg)) {
void grpc_server_add_listener(
grpc_server *server, void *arg,
void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
size_t pollset_count, grpc_call_list *call_list),
void (*destroy)(grpc_server *server, void *arg, grpc_closure *on_done,
grpc_call_list *call_list),
grpc_call_list *call_list) {
listener *l = gpr_malloc(sizeof(listener));
l->arg = arg;
l->start = start;
@ -1096,18 +1119,19 @@ void grpc_server_add_listener(grpc_server *server, void *arg,
}
static grpc_call_error queue_call_request(grpc_server *server,
requested_call *rc) {
requested_call *rc,
grpc_call_list *call_list) {
call_data *calld = NULL;
request_matcher *request_matcher = NULL;
int request_id;
if (gpr_atm_acq_load(&server->shutdown_flag)) {
fail_call(server, rc);
fail_call(server, rc, call_list);
return GRPC_CALL_OK;
}
request_id = gpr_stack_lockfree_pop(server->request_freelist);
if (request_id == -1) {
/* out of request ids: just fail this one */
fail_call(server, rc);
fail_call(server, rc, call_list);
return GRPC_CALL_OK;
}
switch (rc->type) {
@ -1135,12 +1159,13 @@ static grpc_call_error queue_call_request(grpc_server *server,
grpc_closure_init(
&calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
grpc_workqueue_push(server->workqueue, &calld->kill_zombie_closure, 1);
grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
} else {
GPR_ASSERT(calld->state == PENDING);
calld->state = ACTIVATED;
gpr_mu_unlock(&calld->mu_state);
begin_call(server, calld, &server->requested_calls[request_id]);
begin_call(server, calld, &server->requested_calls[request_id],
call_list);
}
gpr_mu_lock(&server->mu_call);
}
@ -1154,13 +1179,16 @@ grpc_call_error grpc_server_request_call(
grpc_metadata_array *initial_metadata,
grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag) {
grpc_call_error error;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
requested_call *rc = gpr_malloc(sizeof(*rc));
GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
initial_metadata, cq_bound_to_call,
cq_for_notification, tag);
if (!grpc_cq_is_server_cq(cq_for_notification)) {
gpr_free(rc);
return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
goto done;
}
grpc_cq_begin_op(cq_for_notification);
details->reserved = NULL;
@ -1172,7 +1200,10 @@ grpc_call_error grpc_server_request_call(
rc->call = call;
rc->data.batch.details = details;
rc->data.batch.initial_metadata = initial_metadata;
return queue_call_request(server, rc);
error = queue_call_request(server, rc, &call_list);
done:
grpc_call_list_run(&call_list);
return error;
}
grpc_call_error grpc_server_request_registered_call(
@ -1180,11 +1211,14 @@ grpc_call_error grpc_server_request_registered_call(
grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag) {
grpc_call_error error;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
requested_call *rc = gpr_malloc(sizeof(*rc));
registered_method *registered_method = rm;
if (!grpc_cq_is_server_cq(cq_for_notification)) {
gpr_free(rc);
return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
goto done;
}
grpc_cq_begin_op(cq_for_notification);
rc->type = REGISTERED_CALL;
@ -1197,12 +1231,16 @@ grpc_call_error grpc_server_request_registered_call(
rc->data.registered.deadline = deadline;
rc->data.registered.initial_metadata = initial_metadata;
rc->data.registered.optional_payload = optional_payload;
return queue_call_request(server, rc);
error = queue_call_request(server, rc, &call_list);
done:
grpc_call_list_run(&call_list);
return error;
}
static void publish_registered_or_batch(grpc_call *call, int success,
void *tag);
static void publish_was_not_set(grpc_call *call, int success, void *tag) {
static void publish_registered_or_batch(grpc_call *call, int success, void *tag,
grpc_call_list *call_list);
static void publish_was_not_set(grpc_call *call, int success, void *tag,
grpc_call_list *call_list) {
abort();
}
@ -1218,7 +1256,7 @@ static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
}
static void begin_call(grpc_server *server, call_data *calld,
requested_call *rc) {
requested_call *rc, grpc_call_list *call_list) {
grpc_ioreq_completion_func publish = publish_was_not_set;
grpc_ioreq req[2];
grpc_ioreq *r = req;
@ -1229,7 +1267,7 @@ static void begin_call(grpc_server *server, call_data *calld,
fill in the metadata array passed by the client, we need to perform
an ioreq op, that should complete immediately. */
grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call);
grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call, call_list);
*rc->call = calld->call;
calld->cq_new = rc->cq_for_notification;
switch (rc->type) {
@ -1265,10 +1303,11 @@ static void begin_call(grpc_server *server, call_data *calld,
GRPC_CALL_INTERNAL_REF(calld->call, "server");
grpc_call_start_ioreq_and_call_back(calld->call, req, (size_t)(r - req),
publish, rc);
publish, rc, call_list);
}
static void done_request_event(void *req, grpc_cq_completion *c) {
static void done_request_event(void *req, grpc_cq_completion *c,
grpc_call_list *call_list) {
requested_call *rc = req;
grpc_server *server = rc->server;
@ -1281,10 +1320,11 @@ static void done_request_event(void *req, grpc_cq_completion *c) {
gpr_free(req);
}
server_unref(server);
server_unref(server, call_list);
}
static void fail_call(grpc_server *server, requested_call *rc) {
static void fail_call(grpc_server *server, requested_call *rc,
grpc_call_list *call_list) {
*rc->call = NULL;
switch (rc->type) {
case BATCH_CALL:
@ -1296,11 +1336,11 @@ static void fail_call(grpc_server *server, requested_call *rc) {
}
server_ref(server);
grpc_cq_end_op(rc->cq_for_notification, rc->tag, 0, done_request_event, rc,
&rc->completion);
&rc->completion, call_list);
}
static void publish_registered_or_batch(grpc_call *call, int success,
void *prc) {
static void publish_registered_or_batch(grpc_call *call, int success, void *prc,
grpc_call_list *call_list) {
grpc_call_element *elem =
grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
requested_call *rc = prc;
@ -1308,7 +1348,7 @@ static void publish_registered_or_batch(grpc_call *call, int success,
channel_data *chand = elem->channel_data;
server_ref(chand->server);
grpc_cq_end_op(calld->cq_new, rc->tag, success, done_request_event, rc,
&rc->completion);
&rc->completion, call_list);
GRPC_CALL_INTERNAL_UNREF(call, "server", call_list);
}

@ -49,9 +49,9 @@ void grpc_server_add_listener(
grpc_server *server, void *listener,
void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
size_t npollsets, grpc_call_list *call_list),
void (*destroy)(grpc_server *server, void *arg, grpc_call_list *call_list));
void grpc_server_listener_destroy_done(void *server);
void (*destroy)(grpc_server *server, void *arg, grpc_closure *on_done,
grpc_call_list *call_list),
grpc_call_list *call_list);
/* Setup a transport - creates a channel stack, binds the transport to the
server */
@ -59,7 +59,8 @@ void grpc_server_setup_transport(grpc_server *server, grpc_transport *transport,
grpc_channel_filter const **extra_filters,
size_t num_extra_filters, grpc_mdctx *mdctx,
grpc_workqueue *workqueue,
const grpc_channel_args *args);
const grpc_channel_args *args,
grpc_call_list *call_list);
const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server);

@ -43,15 +43,17 @@
#include <grpc/support/useful.h>
static void setup_transport(void *server, grpc_transport *transport,
grpc_mdctx *mdctx, grpc_workqueue *workqueue) {
grpc_mdctx *mdctx, grpc_workqueue *workqueue,
grpc_call_list *call_list) {
static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter};
grpc_server_setup_transport(server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx, workqueue,
grpc_server_get_channel_args(server));
grpc_server_get_channel_args(server), call_list);
}
static void new_transport(void *server, grpc_endpoint *tcp) {
static void new_transport(void *server, grpc_endpoint *tcp,
grpc_call_list *call_list) {
/*
* Beware that the call to grpc_create_chttp2_transport() has to happen before
* grpc_tcp_server_destroy(). This is fine here, but similar code
@ -60,25 +62,27 @@ static void new_transport(void *server, grpc_endpoint *tcp) {
* case.
*/
grpc_mdctx *mdctx = grpc_mdctx_create();
grpc_workqueue *workqueue = grpc_workqueue_create();
grpc_workqueue *workqueue = grpc_workqueue_create(call_list);
grpc_transport *transport = grpc_create_chttp2_transport(
grpc_server_get_channel_args(server), tcp, mdctx, workqueue, 0);
setup_transport(server, transport, mdctx, workqueue);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
grpc_server_get_channel_args(server), tcp, mdctx, 0, call_list);
setup_transport(server, transport, mdctx, workqueue, call_list);
grpc_chttp2_transport_start_reading(transport, NULL, 0, call_list);
}
/* Server callback: start listening on our ports */
static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets,
size_t pollset_count) {
size_t pollset_count, grpc_call_list *call_list) {
grpc_tcp_server *tcp = tcpp;
grpc_tcp_server_start(tcp, pollsets, pollset_count, new_transport, server);
grpc_tcp_server_start(tcp, pollsets, pollset_count, new_transport, server,
call_list);
}
/* Server callback: destroy the tcp listener (so we don't generate further
callbacks) */
static void destroy(grpc_server *server, void *tcpp) {
static void destroy(grpc_server *server, void *tcpp, grpc_closure *destroy_done,
grpc_call_list *call_list) {
grpc_tcp_server *tcp = tcpp;
grpc_tcp_server_destroy(tcp, grpc_server_listener_destroy_done, server);
grpc_tcp_server_destroy(tcp, destroy_done, call_list);
}
int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
@ -88,6 +92,7 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
unsigned count = 0;
int port_num = -1;
int port_temp;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
resolved = grpc_blocking_resolve_address(addr, "http");
if (!resolved) {
@ -124,9 +129,8 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
grpc_resolved_addresses_destroy(resolved);
/* Register with the server only upon success */
grpc_server_add_listener(server, tcp, start, destroy);
return port_num;
grpc_server_add_listener(server, tcp, start, destroy, &call_list);
goto done;
/* Error path: cleanup and return */
error:
@ -136,5 +140,9 @@ error:
if (tcp) {
grpc_tcp_server_destroy(tcp, NULL, NULL);
}
port_num = 0;
done:
grpc_call_list_run(&call_list);
return 0;
}

@ -71,7 +71,8 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;

@ -36,6 +36,7 @@
/* Parser for GRPC streams embedded in DATA frames */
#include "src/core/iomgr/iomgr.h"
#include <grpc/support/slice.h>
#include <grpc/support/slice_buffer.h>
#include "src/core/transport/stream_op.h"
@ -74,7 +75,8 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
frame */
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list);
/* create a slice with an empty data frame and is_last set */
gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id);

@ -64,7 +64,8 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;

@ -34,6 +34,7 @@
#ifndef GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_GOAWAY_H
#define GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_GOAWAY_H
#include "src/core/iomgr/iomgr.h"
#include "src/core/transport/chttp2/frame.h"
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
@ -66,7 +67,8 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
grpc_chttp2_goaway_parser *parser, gpr_uint32 length, gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list);
void grpc_chttp2_goaway_append(gpr_uint32 last_stream_id, gpr_uint32 error_code,
gpr_slice debug_data,

@ -70,7 +70,8 @@ grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;
@ -89,9 +90,7 @@ grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
for (ping = transport_parsing->pings.next;
ping != &transport_parsing->pings; ping = ping->next) {
if (0 == memcmp(p->opaque_8bytes, ping->id, 8)) {
/* we know no locks are held here, we may as well just call up
* directly */
ping->on_recv->cb(ping->on_recv->cb_arg, 1);
grpc_call_list_add(call_list, ping->on_recv, 1);
}
ping->next->prev = ping->prev;
ping->prev->next = ping->next;

@ -35,6 +35,7 @@
#define GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_PING_H
#include <grpc/support/slice.h>
#include "src/core/iomgr/iomgr.h"
#include "src/core/transport/chttp2/frame.h"
typedef struct {
@ -49,6 +50,7 @@ grpc_chttp2_parse_error grpc_chttp2_ping_parser_begin_frame(
grpc_chttp2_ping_parser *parser, gpr_uint32 length, gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_PING_H */

@ -72,7 +72,8 @@ grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;

@ -36,6 +36,7 @@
#include <grpc/support/slice.h>
#include "src/core/transport/chttp2/frame.h"
#include "src/core/iomgr/iomgr.h"
typedef struct {
gpr_uint8 byte;
@ -48,6 +49,7 @@ grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_rst_stream_parser *parser, gpr_uint32 length, gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H */

@ -139,7 +139,8 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
void *p, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list) {
grpc_chttp2_settings_parser *parser = p;
const gpr_uint8 *cur = GPR_SLICE_START_PTR(slice);
const gpr_uint8 *end = GPR_SLICE_END_PTR(slice);

@ -37,6 +37,7 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
#include "src/core/transport/chttp2/frame.h"
#include "src/core/iomgr/iomgr.h"
typedef enum {
GRPC_CHTTP2_SPS_ID0,
@ -95,6 +96,7 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
gpr_uint32 *settings);
grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_SETTINGS_H */

@ -75,7 +75,8 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list) {
gpr_uint8 *const beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;

@ -34,6 +34,7 @@
#ifndef GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H
#define GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H
#include "src/core/iomgr/iomgr.h"
#include <grpc/support/slice.h>
#include "src/core/transport/chttp2/frame.h"
@ -51,6 +52,7 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H */

@ -1379,7 +1379,8 @@ int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
void *hpack_parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list) {
grpc_chttp2_hpack_parser *parser = hpack_parser;
if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice),
GPR_SLICE_END_PTR(slice))) {

@ -37,6 +37,7 @@
#include <stddef.h>
#include <grpc/support/port_platform.h>
#include "src/core/iomgr/iomgr.h"
#include "src/core/transport/chttp2/frame.h"
#include "src/core/transport/chttp2/hpack_table.h"
#include "src/core/transport/metadata.h"
@ -108,6 +109,7 @@ int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
the transport */
grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
void *hpack_parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HPACK_PARSER_H */

@ -163,8 +163,6 @@ typedef struct grpc_chttp2_outstanding_ping {
typedef struct {
/** data to write next write */
gpr_slice_buffer qbuf;
/** queued callbacks */
grpc_call_list run_at_unlock;
/** window available for us to send to peer */
gpr_int64 outgoing_window;
@ -269,7 +267,8 @@ struct grpc_chttp2_transport_parsing {
grpc_chttp2_stream_parsing *incoming_stream;
grpc_chttp2_parse_error (*parser)(
void *parser_user_data, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list);
/* received settings */
gpr_uint32 settings[GRPC_CHTTP2_NUM_SETTINGS];
@ -469,19 +468,23 @@ struct grpc_chttp2_stream {
int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_writing *writing);
void grpc_chttp2_perform_writes(
grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint);
void grpc_chttp2_terminate_writing(void *transport_writing, int success);
grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint,
grpc_call_list *call_list);
void grpc_chttp2_terminate_writing(void *transport_writing, int success,
grpc_call_list *call_list);
void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_writing *writing);
grpc_chttp2_transport_writing *writing,
grpc_call_list *call_list);
void grpc_chttp2_prepare_to_read(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_parsing *parsing);
/** Process one slice of incoming data; return 1 if the connection is still
viable after reading, or 0 if the connection should be torn down */
int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice);
gpr_slice slice, grpc_call_list *call_list);
void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_parsing *parsing);
grpc_chttp2_transport_parsing *parsing,
grpc_call_list *call_list);
/** Get a writable stream
returns non-zero if there was a stream available */
@ -574,7 +577,7 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
void grpc_chttp2_add_incoming_goaway(
grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error,
gpr_slice goaway_text);
gpr_slice goaway_text, grpc_call_list *call_list);
void grpc_chttp2_register_stream(grpc_chttp2_transport *t,
grpc_chttp2_stream *s);

@ -59,7 +59,8 @@ static int init_skip_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing, int is_header);
static int parse_frame_slice(grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice, int is_last);
gpr_slice slice, int is_last,
grpc_call_list *call_list);
void grpc_chttp2_prepare_to_read(
grpc_chttp2_transport_global *transport_global,
@ -90,9 +91,9 @@ void grpc_chttp2_prepare_to_read(
}
}
void grpc_chttp2_publish_reads(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_parsing *transport_parsing) {
void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_parsing *transport_parsing,
grpc_call_list *call_list) {
grpc_chttp2_stream_global *stream_global;
grpc_chttp2_stream_parsing *stream_parsing;
@ -132,7 +133,7 @@ void grpc_chttp2_publish_reads(
if (transport_parsing->goaway_received) {
grpc_chttp2_add_incoming_goaway(transport_global,
(gpr_uint32)transport_parsing->goaway_error,
transport_parsing->goaway_text);
transport_parsing->goaway_text, call_list);
transport_parsing->goaway_text = gpr_empty_slice();
transport_parsing->goaway_received = 0;
}
@ -235,7 +236,7 @@ void grpc_chttp2_publish_reads(
}
int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice) {
gpr_slice slice, grpc_call_list *call_list) {
gpr_uint8 *beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg;
@ -364,7 +365,8 @@ int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
transport_parsing->incoming_stream_id;
}
if (transport_parsing->incoming_frame_size == 0) {
if (!parse_frame_slice(transport_parsing, gpr_empty_slice(), 1)) {
if (!parse_frame_slice(transport_parsing, gpr_empty_slice(), 1,
call_list)) {
return 0;
}
transport_parsing->incoming_stream = NULL;
@ -384,7 +386,7 @@ int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
if (!parse_frame_slice(transport_parsing,
gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
(size_t)(end - beg)),
1)) {
1, call_list)) {
return 0;
}
transport_parsing->deframe_state = GRPC_DTS_FH_0;
@ -398,7 +400,7 @@ int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice_sub_no_ref(
slice, cur_offset,
cur_offset + transport_parsing->incoming_frame_size),
1)) {
1, call_list)) {
return 0;
}
cur += transport_parsing->incoming_frame_size;
@ -408,7 +410,7 @@ int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
if (!parse_frame_slice(transport_parsing,
gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
(size_t)(end - beg)),
0)) {
0, call_list)) {
return 0;
}
transport_parsing->incoming_frame_size -= (gpr_uint32)(end - cur);
@ -470,7 +472,8 @@ static int init_frame_parser(grpc_chttp2_transport_parsing *transport_parsing) {
static grpc_chttp2_parse_error skip_parser(
void *parser, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last,
grpc_call_list *call_list) {
return GRPC_CHTTP2_PARSE_OK;
}
@ -789,12 +792,13 @@ static int is_window_update_legal(gpr_int64 window_update, gpr_int64 window) {
*/
static int parse_frame_slice(grpc_chttp2_transport_parsing *transport_parsing,
gpr_slice slice, int is_last) {
gpr_slice slice, int is_last,
grpc_call_list *call_list) {
grpc_chttp2_stream_parsing *stream_parsing =
transport_parsing->incoming_stream;
switch (transport_parsing->parser(transport_parsing->parser_data,
transport_parsing, stream_parsing, slice,
is_last)) {
is_last, call_list)) {
case GRPC_CHTTP2_PARSE_OK:
if (stream_parsing) {
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,

@ -163,7 +163,8 @@ int grpc_chttp2_unlocking_check_writes(
}
void grpc_chttp2_perform_writes(
grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint) {
grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint,
grpc_call_list *call_list) {
GPR_ASSERT(transport_writing->outbuf.count > 0 ||
grpc_chttp2_list_have_writing_streams(transport_writing));
@ -172,17 +173,8 @@ void grpc_chttp2_perform_writes(
GPR_ASSERT(transport_writing->outbuf.count > 0);
GPR_ASSERT(endpoint);
switch (grpc_endpoint_write(endpoint, &transport_writing->outbuf,
&transport_writing->done_cb)) {
case GRPC_ENDPOINT_DONE:
grpc_chttp2_terminate_writing(transport_writing, 1);
break;
case GRPC_ENDPOINT_ERROR:
grpc_chttp2_terminate_writing(transport_writing, 0);
break;
case GRPC_ENDPOINT_PENDING:
break;
}
grpc_endpoint_write(endpoint, &transport_writing->outbuf,
&transport_writing->done_cb, call_list);
}
static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) {
@ -220,7 +212,8 @@ static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) {
void grpc_chttp2_cleanup_writing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing) {
grpc_chttp2_transport_writing *transport_writing,
grpc_call_list *call_list) {
grpc_chttp2_stream_writing *stream_writing;
grpc_chttp2_stream_global *stream_global;
@ -238,8 +231,7 @@ void grpc_chttp2_cleanup_writing(
stream_global->outgoing_sopb->nops == 0) {
GPR_ASSERT(stream_global->write_state != GRPC_WRITE_STATE_QUEUED_CLOSE);
stream_global->outgoing_sopb = NULL;
grpc_call_list_add(&transport_global->run_at_unlock,
stream_global->send_done_closure, 1);
grpc_call_list_add(call_list, stream_global->send_done_closure, 1);
}
}
stream_global->writing_now = 0;

@ -78,27 +78,31 @@ int grpc_flowctl_trace = 0;
static const grpc_transport_vtable vtable;
static void lock(grpc_chttp2_transport *t);
static void unlock(grpc_chttp2_transport *t);
static void unlock(grpc_chttp2_transport *t, grpc_call_list *call_list);
static void unlock_check_read_write_state(grpc_chttp2_transport *t);
static void unlock_check_read_write_state(grpc_chttp2_transport *t,
grpc_call_list *call_list);
/* forward declarations of various callbacks that we'll build closures around */
static void writing_action(void *t, int iomgr_success_ignored);
static void writing_action(void *t, int iomgr_success_ignored,
grpc_call_list *call_list);
/** Set a transport level setting, and push it to our peer */
static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
gpr_uint32 value);
/** Endpoint callback to process incoming data */
static void recv_data(void *tp, int success);
static void recv_data(void *tp, int success, grpc_call_list *call_list);
/** Start disconnection chain */
static void drop_connection(grpc_chttp2_transport *t);
static void drop_connection(grpc_chttp2_transport *t,
grpc_call_list *call_list);
/** Perform a transport_op */
static void perform_stream_op_locked(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op);
grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op,
grpc_call_list *call_list);
/** Cancel a stream: coming from the transport API */
static void cancel_from_api(grpc_chttp2_transport_global *transport_global,
@ -112,23 +116,27 @@ static void close_from_api(grpc_chttp2_transport_global *transport_global,
/** Add endpoint from this transport to pollset */
static void add_to_pollset_locked(grpc_chttp2_transport *t,
grpc_pollset *pollset);
grpc_pollset *pollset,
grpc_call_list *call_list);
static void add_to_pollset_set_locked(grpc_chttp2_transport *t,
grpc_pollset_set *pollset_set);
grpc_pollset_set *pollset_set,
grpc_call_list *call_list);
/** Start new streams that have been created if we can */
static void maybe_start_some_streams(
grpc_chttp2_transport_global *transport_global);
grpc_chttp2_transport_global *transport_global, grpc_call_list *call_list);
static void connectivity_state_set(
grpc_chttp2_transport_global *transport_global,
grpc_connectivity_state state, const char *reason);
grpc_connectivity_state state, const char *reason,
grpc_call_list *call_list);
/*
* CONSTRUCTION/DESTRUCTION/REFCOUNTING
*/
static void destruct_transport(grpc_chttp2_transport *t) {
static void destruct_transport(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
size_t i;
gpr_mu_lock(&t->mu);
@ -157,7 +165,8 @@ static void destruct_transport(grpc_chttp2_transport *t) {
grpc_chttp2_stream_map_destroy(&t->parsing_stream_map);
grpc_chttp2_stream_map_destroy(&t->new_stream_map);
grpc_connectivity_state_destroy(&t->channel_callback.state_tracker);
grpc_connectivity_state_destroy(&t->channel_callback.state_tracker,
call_list);
gpr_mu_unlock(&t->mu);
gpr_mu_destroy(&t->mu);
@ -166,7 +175,7 @@ static void destruct_transport(grpc_chttp2_transport *t) {
and maybe they hold resources that need to be freed */
while (t->global.pings.next != &t->global.pings) {
grpc_chttp2_outstanding_ping *ping = t->global.pings.next;
ping->on_recv->cb(ping->on_recv->cb_arg, 0);
grpc_call_list_add(call_list, ping->on_recv, 0);
ping->next->prev = ping->prev;
ping->prev->next = ping->next;
gpr_free(ping);
@ -180,13 +189,13 @@ static void destruct_transport(grpc_chttp2_transport *t) {
#ifdef REFCOUNTING_DEBUG
#define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__)
#define UNREF_TRANSPORT(t, r) unref_transport(t, r, __FILE__, __LINE__)
static void unref_transport(grpc_chttp2_transport *t, const char *reason,
const char *file, int line) {
#define UNREF_TRANSPORT(t, r, cl) unref_transport(t, cl, r, __FILE__, __LINE__)
static void unref_transport(grpc_chttp2_transport *t, grpc_call_list *call_list,
const char *reason, const char *file, int line) {
gpr_log(GPR_DEBUG, "chttp2:unref:%p %d->%d %s [%s:%d]", t, t->refs.count,
t->refs.count - 1, reason, file, line);
if (!gpr_unref(&t->refs)) return;
destruct_transport(t);
destruct_transport(t, call_list);
}
static void ref_transport(grpc_chttp2_transport *t, const char *reason,
@ -197,10 +206,11 @@ static void ref_transport(grpc_chttp2_transport *t, const char *reason,
}
#else
#define REF_TRANSPORT(t, r) ref_transport(t)
#define UNREF_TRANSPORT(t, r) unref_transport(t)
static void unref_transport(grpc_chttp2_transport *t) {
#define UNREF_TRANSPORT(t, r, cl) unref_transport(t, cl)
static void unref_transport(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
if (!gpr_unref(&t->refs)) return;
destruct_transport(t);
destruct_transport(t, call_list);
}
static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
@ -209,7 +219,7 @@ static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
static void init_transport(grpc_chttp2_transport *t,
const grpc_channel_args *channel_args,
grpc_endpoint *ep, grpc_mdctx *mdctx,
grpc_workqueue *workqueue, gpr_uint8 is_client) {
gpr_uint8 is_client, grpc_call_list *call_list) {
size_t i;
int j;
@ -329,15 +339,15 @@ static void init_transport(grpc_chttp2_transport *t,
}
}
static void destroy_transport(grpc_transport *gt) {
static void destroy_transport(grpc_transport *gt, grpc_call_list *call_list) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
lock(t);
t->destroying = 1;
drop_connection(t);
unlock(t);
drop_connection(t, call_list);
unlock(t, call_list);
UNREF_TRANSPORT(t, "destroy");
UNREF_TRANSPORT(t, "destroy", call_list);
}
/** block grpc_endpoint_shutdown being called until a paired
@ -347,45 +357,50 @@ static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) {
gpr_ref(&t->shutdown_ep_refs);
}
static void allow_endpoint_shutdown_locked(grpc_chttp2_transport *t) {
static void allow_endpoint_shutdown_locked(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
if (gpr_unref(&t->shutdown_ep_refs)) {
if (t->ep) {
grpc_endpoint_shutdown(t->ep);
grpc_endpoint_shutdown(t->ep, call_list);
}
}
}
static void allow_endpoint_shutdown_unlocked(grpc_chttp2_transport *t) {
static void allow_endpoint_shutdown_unlocked(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
if (gpr_unref(&t->shutdown_ep_refs)) {
gpr_mu_lock(&t->mu);
if (t->ep) {
grpc_endpoint_shutdown(t->ep);
grpc_endpoint_shutdown(t->ep, call_list);
}
gpr_mu_unlock(&t->mu);
}
}
static void destroy_endpoint(grpc_chttp2_transport *t) {
grpc_endpoint_destroy(t->ep);
static void destroy_endpoint(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
grpc_endpoint_destroy(t->ep, call_list);
t->ep = NULL;
UNREF_TRANSPORT(
t, "disconnect"); /* safe because we'll still have the ref for write */
/* safe because we'll still have the ref for write */
UNREF_TRANSPORT(t, "disconnect", call_list);
}
static void close_transport_locked(grpc_chttp2_transport *t) {
static void close_transport_locked(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
if (!t->closed) {
t->closed = 1;
connectivity_state_set(&t->global, GRPC_CHANNEL_FATAL_FAILURE,
"close_transport");
"close_transport", call_list);
if (t->ep) {
allow_endpoint_shutdown_locked(t);
allow_endpoint_shutdown_locked(t, call_list);
}
}
}
static int init_stream(grpc_transport *gt, grpc_stream *gs,
const void *server_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
@ -416,13 +431,15 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs,
s->global.in_stream_map = 1;
}
if (initial_op) perform_stream_op_locked(&t->global, &s->global, initial_op);
unlock(t);
if (initial_op)
perform_stream_op_locked(&t->global, &s->global, initial_op, call_list);
unlock(t, call_list);
return 0;
}
static void destroy_stream(grpc_transport *gt, grpc_stream *gs) {
static void destroy_stream(grpc_transport *gt, grpc_stream *gs,
grpc_call_list *call_list) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
int i;
@ -433,7 +450,7 @@ static void destroy_stream(grpc_transport *gt, grpc_stream *gs) {
s->global.id == 0);
GPR_ASSERT(!s->global.in_stream_map);
if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
close_transport_locked(t);
close_transport_locked(t, call_list);
}
if (!t->parsing_active && s->global.id) {
GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map,
@ -463,7 +480,7 @@ static void destroy_stream(grpc_transport *gt, grpc_stream *gs) {
grpc_chttp2_incoming_metadata_live_op_buffer_end(
&s->global.outstanding_metadata);
UNREF_TRANSPORT(t, "stream");
UNREF_TRANSPORT(t, "stream", call_list);
}
grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream(
@ -498,21 +515,17 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
static void lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); }
static void unlock(grpc_chttp2_transport *t) {
grpc_call_list run = GRPC_CALL_LIST_INIT;
unlock_check_read_write_state(t);
static void unlock(grpc_chttp2_transport *t, grpc_call_list *call_list) {
unlock_check_read_write_state(t, call_list);
if (!t->writing_active && !t->closed &&
grpc_chttp2_unlocking_check_writes(&t->global, &t->writing)) {
t->writing_active = 1;
REF_TRANSPORT(t, "writing");
grpc_call_list_add(&t->global.run_at_unlock, &t->writing_action, 1);
grpc_call_list_add(call_list, &t->writing_action, 1);
prevent_endpoint_shutdown(t);
}
GPR_SWAP(grpc_call_list, run, t->global.run_at_unlock);
gpr_mu_unlock(&t->mu);
grpc_call_list_run(run);
}
/*
@ -534,52 +547,54 @@ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
}
}
void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) {
void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success,
grpc_call_list *call_list) {
grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr;
grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
lock(t);
allow_endpoint_shutdown_locked(t);
allow_endpoint_shutdown_locked(t, call_list);
if (!success) {
drop_connection(t);
drop_connection(t, call_list);
}
/* cleanup writing related jazz */
grpc_chttp2_cleanup_writing(&t->global, &t->writing);
grpc_chttp2_cleanup_writing(&t->global, &t->writing, call_list);
/* leave the writing flag up on shutdown to prevent further writes in unlock()
from starting */
t->writing_active = 0;
if (t->ep && !t->endpoint_reading) {
destroy_endpoint(t);
destroy_endpoint(t, call_list);
}
unlock(t);
unlock(t, call_list);
UNREF_TRANSPORT(t, "writing");
UNREF_TRANSPORT(t, "writing", call_list);
}
static void writing_action(void *gt, int iomgr_success_ignored) {
static void writing_action(void *gt, int iomgr_success_ignored,
grpc_call_list *call_list) {
grpc_chttp2_transport *t = gt;
grpc_chttp2_perform_writes(&t->writing, t->ep);
grpc_chttp2_perform_writes(&t->writing, t->ep, call_list);
}
void grpc_chttp2_add_incoming_goaway(
grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error,
gpr_slice goaway_text) {
gpr_slice goaway_text, grpc_call_list *call_list) {
char *msg = gpr_dump_slice(goaway_text, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg);
gpr_free(msg);
gpr_slice_unref(goaway_text);
transport_global->seen_goaway = 1;
connectivity_state_set(transport_global, GRPC_CHANNEL_FATAL_FAILURE,
"got_goaway");
"got_goaway", call_list);
}
static void maybe_start_some_streams(
grpc_chttp2_transport_global *transport_global) {
grpc_chttp2_transport_global *transport_global, grpc_call_list *call_list) {
grpc_chttp2_stream_global *stream_global;
/* start streams where we have free grpc_chttp2_stream ids and free
* concurrency */
@ -601,7 +616,7 @@ static void maybe_start_some_streams(
if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
connectivity_state_set(transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
"no_more_stream_ids");
"no_more_stream_ids", call_list);
}
stream_global->outgoing_window =
@ -631,7 +646,8 @@ static void maybe_start_some_streams(
static void perform_stream_op_locked(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op) {
grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op,
grpc_call_list *call_list) {
if (op->cancel_with_status != GRPC_STATUS_OK) {
cancel_from_api(transport_global, stream_global, op->cancel_with_status);
}
@ -658,14 +674,13 @@ static void perform_stream_op_locked(
transport_global->is_client ? "CLI" : "SVR", stream_global));
grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
stream_global);
maybe_start_some_streams(transport_global);
maybe_start_some_streams(transport_global, call_list);
} else if (stream_global->outgoing_window > 0) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
}
} else {
grpc_sopb_reset(op->send_ops);
grpc_call_list_add(&transport_global->run_at_unlock,
stream_global->send_done_closure, 0);
grpc_call_list_add(call_list, stream_global->send_done_closure, 0);
}
}
@ -700,20 +715,21 @@ static void perform_stream_op_locked(
if (op->bind_pollset) {
add_to_pollset_locked(TRANSPORT_FROM_GLOBAL(transport_global),
op->bind_pollset);
op->bind_pollset, call_list);
}
grpc_call_list_add(&transport_global->run_at_unlock, op->on_consumed, 1);
grpc_call_list_add(call_list, op->on_consumed, 1);
}
static void perform_stream_op(grpc_transport *gt, grpc_stream *gs,
grpc_transport_stream_op *op) {
grpc_transport_stream_op *op,
grpc_call_list *call_list) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
lock(t);
perform_stream_op_locked(&t->global, &s->global, op);
unlock(t);
perform_stream_op_locked(&t->global, &s->global, op, call_list);
unlock(t, call_list);
}
static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) {
@ -733,18 +749,19 @@ static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) {
gpr_slice_buffer_add(&t->global.qbuf, grpc_chttp2_ping_create(0, p->id));
}
static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op,
grpc_call_list *call_list) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
int close_transport = 0;
lock(t);
grpc_call_list_add(&t->global.run_at_unlock, op->on_consumed, 1);
grpc_call_list_add(call_list, op->on_consumed, 1);
if (op->on_connectivity_state_change) {
grpc_connectivity_state_notify_on_state_change(
&t->channel_callback.state_tracker, op->connectivity_state,
op->on_connectivity_state_change, &t->global.run_at_unlock);
op->on_connectivity_state_change, call_list);
}
if (op->send_goaway) {
@ -763,11 +780,11 @@ static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
}
if (op->bind_pollset) {
add_to_pollset_locked(t, op->bind_pollset);
add_to_pollset_locked(t, op->bind_pollset, call_list);
}
if (op->bind_pollset_set) {
add_to_pollset_set_locked(t, op->bind_pollset_set);
add_to_pollset_set_locked(t, op->bind_pollset_set, call_list);
}
if (op->send_ping) {
@ -775,15 +792,15 @@ static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
}
if (op->disconnect) {
close_transport_locked(t);
close_transport_locked(t, call_list);
}
unlock(t);
unlock(t, call_list);
if (close_transport) {
lock(t);
close_transport_locked(t);
unlock(t);
close_transport_locked(t, call_list);
unlock(t, call_list);
}
}
@ -799,7 +816,8 @@ static grpc_stream_state compute_state(gpr_uint8 write_closed,
return GRPC_STREAM_OPEN;
}
static void remove_stream(grpc_chttp2_transport *t, gpr_uint32 id) {
static void remove_stream(grpc_chttp2_transport *t, gpr_uint32 id,
grpc_call_list *call_list) {
size_t new_stream_count;
grpc_chttp2_stream *s =
grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
@ -814,7 +832,7 @@ static void remove_stream(grpc_chttp2_transport *t, gpr_uint32 id) {
grpc_chttp2_parsing_become_skip_parser(&t->parsing);
}
if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
close_transport_locked(t);
close_transport_locked(t, call_list);
}
new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
@ -822,11 +840,12 @@ static void remove_stream(grpc_chttp2_transport *t, gpr_uint32 id) {
GPR_ASSERT(new_stream_count <= GPR_UINT32_MAX);
if (new_stream_count != t->global.concurrent_stream_count) {
t->global.concurrent_stream_count = (gpr_uint32)new_stream_count;
maybe_start_some_streams(&t->global);
maybe_start_some_streams(&t->global, call_list);
}
}
static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
static void unlock_check_read_write_state(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
grpc_chttp2_transport_global *transport_global = &t->global;
grpc_chttp2_stream_global *stream_global;
grpc_stream_state state;
@ -840,7 +859,7 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
GPR_ASSERT(stream_global->in_stream_map);
GPR_ASSERT(stream_global->write_state != GRPC_WRITE_STATE_OPEN);
GPR_ASSERT(stream_global->read_closed);
remove_stream(t, stream_global->id);
remove_stream(t, stream_global->id, call_list);
grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global);
}
@ -866,8 +885,7 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
if (stream_global->outgoing_sopb != NULL) {
grpc_sopb_reset(stream_global->outgoing_sopb);
stream_global->outgoing_sopb = NULL;
grpc_call_list_add(&transport_global->run_at_unlock,
stream_global->send_done_closure, 1);
grpc_call_list_add(call_list, stream_global->send_done_closure, 1);
}
stream_global->read_closed = 1;
if (!stream_global->published_cancelled) {
@ -889,7 +907,7 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global,
stream_global);
} else {
remove_stream(t, stream_global->id);
remove_stream(t, stream_global->id, call_list);
}
}
if (!stream_global->publish_sopb) {
@ -917,8 +935,7 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
&stream_global->outstanding_metadata);
grpc_sopb_swap(stream_global->publish_sopb, &stream_global->incoming_sopb);
stream_global->published_state = *stream_global->publish_state = state;
grpc_call_list_add(&transport_global->run_at_unlock,
stream_global->recv_done_closure, 1);
grpc_call_list_add(call_list, stream_global->recv_done_closure, 1);
stream_global->recv_done_closure = NULL;
stream_global->publish_sopb = NULL;
stream_global->publish_state = NULL;
@ -1053,8 +1070,9 @@ static void end_all_the_calls(grpc_chttp2_transport *t) {
grpc_chttp2_for_all_streams(&t->global, NULL, cancel_stream_cb);
}
static void drop_connection(grpc_chttp2_transport *t) {
close_transport_locked(t);
static void drop_connection(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
close_transport_locked(t, call_list);
end_all_the_calls(t);
}
@ -1079,17 +1097,19 @@ static void update_global_window(void *args, gpr_uint32 id, void *stream) {
}
}
static void read_error_locked(grpc_chttp2_transport *t) {
static void read_error_locked(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
t->endpoint_reading = 0;
if (!t->writing_active && t->ep) {
destroy_endpoint(t);
destroy_endpoint(t, call_list);
}
}
/* tcp read callback */
static int recv_data_loop(grpc_chttp2_transport *t, int *success) {
static void recv_data(void *tp, int success, grpc_call_list *call_list) {
size_t i;
int keep_reading = 0;
grpc_chttp2_transport *t = tp;
lock(t);
i = 0;
@ -1102,12 +1122,13 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) {
grpc_chttp2_prepare_to_read(&t->global, &t->parsing);
gpr_mu_unlock(&t->mu);
for (; i < t->read_buffer.count &&
grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i]);
grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i],
call_list);
i++)
;
gpr_mu_lock(&t->mu);
if (i != t->read_buffer.count) {
drop_connection(t);
drop_connection(t, call_list);
}
/* merge stream lists */
grpc_chttp2_stream_map_move_into(&t->new_stream_map,
@ -1120,52 +1141,27 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) {
t->parsing.initial_window_update = 0;
}
/* handle higher level things */
grpc_chttp2_publish_reads(&t->global, &t->parsing);
grpc_chttp2_publish_reads(&t->global, &t->parsing, call_list);
t->parsing_active = 0;
}
if (!*success || i != t->read_buffer.count) {
drop_connection(t);
read_error_locked(t);
if (!success || i != t->read_buffer.count) {
drop_connection(t, call_list);
read_error_locked(t, call_list);
} else if (!t->closed) {
keep_reading = 1;
REF_TRANSPORT(t, "keep_reading");
prevent_endpoint_shutdown(t);
}
gpr_slice_buffer_reset_and_unref(&t->read_buffer);
unlock(t);
unlock(t, call_list);
if (keep_reading) {
int ret = -1;
switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) {
case GRPC_ENDPOINT_DONE:
*success = 1;
ret = 1;
break;
case GRPC_ENDPOINT_ERROR:
*success = 0;
ret = 1;
break;
case GRPC_ENDPOINT_PENDING:
ret = 0;
break;
}
allow_endpoint_shutdown_unlocked(t);
UNREF_TRANSPORT(t, "keep_reading");
return ret;
grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data, call_list);
allow_endpoint_shutdown_unlocked(t, call_list);
UNREF_TRANSPORT(t, "keep_reading", call_list);
} else {
UNREF_TRANSPORT(t, "recv_data");
return 0;
UNREF_TRANSPORT(t, "recv_data", call_list);
}
gpr_log(GPR_ERROR, "should never reach here");
abort();
}
static void recv_data(void *tp, int success) {
grpc_chttp2_transport *t = tp;
while (recv_data_loop(t, &success))
;
}
/*
@ -1174,12 +1170,13 @@ static void recv_data(void *tp, int success) {
static void connectivity_state_set(
grpc_chttp2_transport_global *transport_global,
grpc_connectivity_state state, const char *reason) {
grpc_connectivity_state state, const char *reason,
grpc_call_list *call_list) {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
grpc_connectivity_state_set(
&TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker,
state, reason, &transport_global->run_at_unlock);
state, reason, call_list);
}
/*
@ -1187,16 +1184,18 @@ static void connectivity_state_set(
*/
static void add_to_pollset_locked(grpc_chttp2_transport *t,
grpc_pollset *pollset) {
grpc_pollset *pollset,
grpc_call_list *call_list) {
if (t->ep) {
grpc_endpoint_add_to_pollset(t->ep, pollset);
grpc_endpoint_add_to_pollset(t->ep, pollset, call_list);
}
}
static void add_to_pollset_set_locked(grpc_chttp2_transport *t,
grpc_pollset_set *pollset_set) {
grpc_pollset_set *pollset_set,
grpc_call_list *call_list) {
if (t->ep) {
grpc_endpoint_add_to_pollset_set(t->ep, pollset_set);
grpc_endpoint_add_to_pollset_set(t->ep, pollset_set, call_list);
}
}
@ -1235,7 +1234,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *reason,
* INTEGRATION GLUE
*/
static char *chttp2_get_peer(grpc_transport *t) {
static char *chttp2_get_peer(grpc_transport *t, grpc_call_list *call_list) {
return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string);
}
@ -1249,16 +1248,17 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
grpc_transport *grpc_create_chttp2_transport(
const grpc_channel_args *channel_args, grpc_endpoint *ep, grpc_mdctx *mdctx,
grpc_workqueue *workqueue, int is_client) {
int is_client, grpc_call_list *call_list) {
grpc_chttp2_transport *t = gpr_malloc(sizeof(grpc_chttp2_transport));
init_transport(t, channel_args, ep, mdctx, workqueue, is_client != 0);
init_transport(t, channel_args, ep, mdctx, is_client != 0, call_list);
return &t->base;
}
void grpc_chttp2_transport_start_reading(grpc_transport *transport,
gpr_slice *slices, size_t nslices) {
gpr_slice *slices, size_t nslices,
grpc_call_list *call_list) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */
gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
recv_data(t, 1);
recv_data(t, 1, call_list);
}

@ -42,9 +42,10 @@ extern int grpc_flowctl_trace;
grpc_transport *grpc_create_chttp2_transport(
const grpc_channel_args *channel_args, grpc_endpoint *ep,
grpc_mdctx *metadata_context, int is_client);
grpc_mdctx *metadata_context, int is_client, grpc_call_list *call_list);
void grpc_chttp2_transport_start_reading(grpc_transport *transport,
gpr_slice *slices, size_t nslices);
gpr_slice *slices, size_t nslices,
grpc_call_list *call_list);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_TRANSPORT_H */

@ -66,7 +66,8 @@ void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
tracker->name = gpr_strdup(name);
}
void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker) {
void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker,
grpc_call_list *call_list) {
int success;
grpc_connectivity_state_watcher *w;
while ((w = tracker->watchers)) {
@ -78,7 +79,7 @@ void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker) {
} else {
success = 0;
}
w->notify->cb(w->notify->cb_arg, success);
grpc_call_list_add(call_list, w->notify, success);
gpr_free(w);
}
gpr_free(tracker->name);

@ -61,7 +61,8 @@ extern int grpc_connectivity_state_trace;
void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state init_state,
const char *name);
void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker);
void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker *tracker,
grpc_call_list *call_list);
/** Set connectivity state; not thread safe; access must be serialized with an
* external lock */

@ -40,48 +40,47 @@ size_t grpc_transport_stream_size(grpc_transport *transport) {
return transport->vtable->sizeof_stream;
}
void grpc_transport_destroy(grpc_transport *transport) {
transport->vtable->destroy(transport);
void grpc_transport_destroy(grpc_transport *transport,
grpc_call_list *call_list) {
transport->vtable->destroy(transport, call_list);
}
int grpc_transport_init_stream(grpc_transport *transport, grpc_stream *stream,
const void *server_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
return transport->vtable->init_stream(transport, stream, server_data,
initial_op);
initial_op, call_list);
}
void grpc_transport_perform_stream_op(grpc_transport *transport,
grpc_stream *stream,
grpc_transport_stream_op *op) {
transport->vtable->perform_stream_op(transport, stream, op);
grpc_transport_stream_op *op,
grpc_call_list *call_list) {
transport->vtable->perform_stream_op(transport, stream, op, call_list);
}
void grpc_transport_perform_op(grpc_transport *transport,
grpc_transport_op *op) {
transport->vtable->perform_op(transport, op);
void grpc_transport_perform_op(grpc_transport *transport, grpc_transport_op *op,
grpc_call_list *call_list) {
transport->vtable->perform_op(transport, op, call_list);
}
void grpc_transport_destroy_stream(grpc_transport *transport,
grpc_stream *stream) {
transport->vtable->destroy_stream(transport, stream);
grpc_stream *stream,
grpc_call_list *call_list) {
transport->vtable->destroy_stream(transport, stream, call_list);
}
char *grpc_transport_get_peer(grpc_transport *transport) {
return transport->vtable->get_peer(transport);
char *grpc_transport_get_peer(grpc_transport *transport,
grpc_call_list *call_list) {
return transport->vtable->get_peer(transport, call_list);
}
void grpc_transport_stream_op_finish_with_failure(
grpc_transport_stream_op *op) {
if (op->send_ops) {
op->on_done_send->cb(op->on_done_send->cb_arg, 0);
}
if (op->recv_ops) {
op->on_done_recv->cb(op->on_done_recv->cb_arg, 0);
}
if (op->on_consumed) {
op->on_consumed->cb(op->on_consumed->cb_arg, 0);
}
void grpc_transport_stream_op_finish_with_failure(grpc_transport_stream_op *op,
grpc_call_list *call_list) {
grpc_call_list_add(call_list, op->on_done_recv, 0);
grpc_call_list_add(call_list, op->on_done_send, 0);
grpc_call_list_add(call_list, op->on_consumed, 0);
}
void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
@ -105,11 +104,12 @@ typedef struct {
grpc_closure closure;
} close_message_data;
static void free_message(void *p, int iomgr_success) {
static void free_message(void *p, int iomgr_success,
grpc_call_list *call_list) {
close_message_data *cmd = p;
gpr_slice_unref(cmd->message);
if (cmd->then_call != NULL) {
cmd->then_call->cb(cmd->then_call->cb_arg, iomgr_success);
cmd->then_call->cb(cmd->then_call->cb_arg, iomgr_success, call_list);
}
gpr_free(cmd);
}

@ -136,7 +136,8 @@ size_t grpc_transport_stream_size(grpc_transport *transport);
supplied from the accept_stream callback function */
int grpc_transport_init_stream(grpc_transport *transport, grpc_stream *stream,
const void *server_data,
grpc_transport_stream_op *initial_op);
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list);
/* Destroy transport data for a stream.
@ -149,9 +150,11 @@ int grpc_transport_init_stream(grpc_transport *transport, grpc_stream *stream,
stream - the grpc_stream to destroy (memory is still owned by the
caller, but any child memory must be cleaned up) */
void grpc_transport_destroy_stream(grpc_transport *transport,
grpc_stream *stream);
grpc_stream *stream,
grpc_call_list *call_list);
void grpc_transport_stream_op_finish_with_failure(grpc_transport_stream_op *op);
void grpc_transport_stream_op_finish_with_failure(grpc_transport_stream_op *op,
grpc_call_list *call_list);
void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
grpc_status_code status);
@ -173,10 +176,11 @@ char *grpc_transport_stream_op_string(grpc_transport_stream_op *op);
op - a grpc_transport_stream_op specifying the op to perform */
void grpc_transport_perform_stream_op(grpc_transport *transport,
grpc_stream *stream,
grpc_transport_stream_op *op);
grpc_transport_stream_op *op,
grpc_call_list *call_list);
void grpc_transport_perform_op(grpc_transport *transport,
grpc_transport_op *op);
void grpc_transport_perform_op(grpc_transport *transport, grpc_transport_op *op,
grpc_call_list *call_list);
/* Send a ping on a transport
@ -191,9 +195,11 @@ void grpc_transport_goaway(grpc_transport *transport, grpc_status_code status,
void grpc_transport_close(grpc_transport *transport);
/* Destroy the transport */
void grpc_transport_destroy(grpc_transport *transport);
void grpc_transport_destroy(grpc_transport *transport,
grpc_call_list *call_list);
/* Get the transports peer */
char *grpc_transport_get_peer(grpc_transport *transport);
char *grpc_transport_get_peer(grpc_transport *transport,
grpc_call_list *call_list);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_TRANSPORT_H */

@ -44,23 +44,27 @@ typedef struct grpc_transport_vtable {
/* implementation of grpc_transport_init_stream */
int (*init_stream)(grpc_transport *self, grpc_stream *stream,
const void *server_data,
grpc_transport_stream_op *initial_op);
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list);
/* implementation of grpc_transport_perform_stream_op */
void (*perform_stream_op)(grpc_transport *self, grpc_stream *stream,
grpc_transport_stream_op *op);
grpc_transport_stream_op *op,
grpc_call_list *call_list);
/* implementation of grpc_transport_perform_op */
void (*perform_op)(grpc_transport *self, grpc_transport_op *op);
void (*perform_op)(grpc_transport *self, grpc_transport_op *op,
grpc_call_list *call_list);
/* implementation of grpc_transport_destroy_stream */
void (*destroy_stream)(grpc_transport *self, grpc_stream *stream);
void (*destroy_stream)(grpc_transport *self, grpc_stream *stream,
grpc_call_list *call_list);
/* implementation of grpc_transport_destroy */
void (*destroy)(grpc_transport *self);
void (*destroy)(grpc_transport *self, grpc_call_list *call_list);
/* implementation of grpc_transport_get_peer */
char *(*get_peer)(grpc_transport *self);
char *(*get_peer)(grpc_transport *self, grpc_call_list *call_list);
} grpc_transport_vtable;
/* an instance of a grpc transport */

@ -70,9 +70,11 @@ static void server_setup_transport(void *ts, grpc_transport *transport,
thd_args *a = ts;
static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter};
grpc_server_setup_transport(a->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx, workqueue,
grpc_server_get_channel_args(a->server));
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_server_setup_transport(
a->server, transport, extra_filters, GPR_ARRAY_SIZE(extra_filters), mdctx,
workqueue, grpc_server_get_channel_args(a->server), &call_list);
grpc_call_list_run(&call_list);
}
void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator,
@ -116,9 +118,11 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator,
a.validator = validator;
grpc_server_register_completion_queue(a.server, a.cq, NULL);
grpc_server_start(a.server);
transport = grpc_create_chttp2_transport(NULL, sfd.server, mdctx, 0);
transport =
grpc_create_chttp2_transport(NULL, sfd.server, mdctx, 0, &call_list);
server_setup_transport(&a, transport, mdctx, workqueue);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
grpc_chttp2_transport_start_reading(transport, NULL, 0, &call_list);
grpc_call_list_run(&call_list);
/* Bind everything into the same pollset */
grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(a.cq), &call_list);

@ -44,7 +44,7 @@
static void channel_init_func(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args,
grpc_mdctx *metadata_context, int is_first,
int is_last) {
int is_last, grpc_call_list *call_list) {
GPR_ASSERT(args->num_args == 1);
GPR_ASSERT(args->args[0].type == GRPC_ARG_INTEGER);
GPR_ASSERT(0 == strcmp(args->args[0].key, "test_key"));
@ -56,26 +56,33 @@ static void channel_init_func(grpc_channel_element *elem, grpc_channel *master,
static void call_init_func(grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
grpc_transport_stream_op *initial_op,
grpc_call_list *call_list) {
++*(int *)(elem->channel_data);
*(int *)(elem->call_data) = 0;
}
static void channel_destroy_func(grpc_channel_element *elem) {}
static void channel_destroy_func(grpc_channel_element *elem,
grpc_call_list *call_list) {}
static void call_destroy_func(grpc_call_element *elem) {
static void call_destroy_func(grpc_call_element *elem,
grpc_call_list *call_list) {
++*(int *)(elem->channel_data);
}
static void call_func(grpc_call_element *elem, grpc_transport_stream_op *op) {
static void call_func(grpc_call_element *elem, grpc_transport_stream_op *op,
grpc_call_list *call_list) {
++*(int *)(elem->call_data);
}
static void channel_func(grpc_channel_element *elem, grpc_transport_op *op) {
static void channel_func(grpc_channel_element *elem, grpc_transport_op *op,
grpc_call_list *call_list) {
++*(int *)(elem->channel_data);
}
static char *get_peer(grpc_call_element *elem) { return gpr_strdup("peer"); }
static char *get_peer(grpc_call_element *elem, grpc_call_list *call_list) {
return gpr_strdup("peer");
}
static void test_create_channel_stack(void) {
const grpc_channel_filter filter = {call_func, channel_func,
@ -93,6 +100,7 @@ static void test_create_channel_stack(void) {
grpc_mdctx *metadata_context;
int *channel_data;
int *call_data;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
metadata_context = grpc_mdctx_create();
@ -105,14 +113,14 @@ static void test_create_channel_stack(void) {
channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1));
grpc_channel_stack_init(&filters, 1, NULL, &chan_args, metadata_context,
channel_stack);
channel_stack, &call_list);
GPR_ASSERT(channel_stack->count == 1);
channel_elem = grpc_channel_stack_element(channel_stack, 0);
channel_data = (int *)channel_elem->channel_data;
GPR_ASSERT(*channel_data == 0);
call_stack = gpr_malloc(channel_stack->call_stack_size);
grpc_call_stack_init(channel_stack, NULL, NULL, call_stack);
grpc_call_stack_init(channel_stack, NULL, NULL, call_stack, &call_list);
GPR_ASSERT(call_stack->count == 1);
call_elem = grpc_call_stack_element(call_stack, 0);
GPR_ASSERT(call_elem->filter == channel_elem->filter);
@ -121,14 +129,16 @@ static void test_create_channel_stack(void) {
GPR_ASSERT(*call_data == 0);
GPR_ASSERT(*channel_data == 1);
grpc_call_stack_destroy(call_stack);
grpc_call_stack_destroy(call_stack, &call_list);
gpr_free(call_stack);
GPR_ASSERT(*channel_data == 2);
grpc_channel_stack_destroy(channel_stack);
grpc_channel_stack_destroy(channel_stack, &call_list);
gpr_free(channel_stack);
grpc_mdctx_unref(metadata_context);
GPR_ASSERT(grpc_call_list_empty(call_list));
}
int main(int argc, char **argv) {

@ -64,9 +64,11 @@ static void server_setup_transport(void *ts, grpc_transport *transport,
grpc_end2end_test_fixture *f = ts;
static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter};
grpc_server_setup_transport(f->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx, g_workqueue,
grpc_server_get_channel_args(f->server));
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_server_setup_transport(
f->server, transport, extra_filters, GPR_ARRAY_SIZE(extra_filters), mdctx,
g_workqueue, grpc_server_get_channel_args(f->server), &call_list);
grpc_call_list_run(&call_list);
}
typedef struct {
@ -75,16 +77,17 @@ typedef struct {
} sp_client_setup;
static void client_setup_transport(void *ts, grpc_transport *transport,
grpc_mdctx *mdctx) {
grpc_mdctx *mdctx,
grpc_call_list *call_list) {
sp_client_setup *cs = ts;
const grpc_channel_filter *filters[] = {&grpc_http_client_filter,
&grpc_compress_filter,
&grpc_connected_channel_filter};
size_t nfilters = sizeof(filters) / sizeof(*filters);
grpc_channel *channel =
grpc_channel_create_from_filters("socketpair-target", filters, nfilters,
cs->client_args, mdctx, g_workqueue, 1);
grpc_channel *channel = grpc_channel_create_from_filters(
"socketpair-target", filters, nfilters, cs->client_args, mdctx,
g_workqueue, 1, call_list);
cs->f->client = channel;
@ -108,20 +111,24 @@ static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f,
grpc_channel_args *client_args) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_endpoint_pair *sfd = f->fixture_data;
grpc_transport *transport;
grpc_mdctx *mdctx = grpc_mdctx_create();
sp_client_setup cs;
cs.client_args = client_args;
cs.f = f;
transport = grpc_create_chttp2_transport(client_args, sfd->client, mdctx, 1);
client_setup_transport(&cs, transport, mdctx);
transport = grpc_create_chttp2_transport(client_args, sfd->client, mdctx, 1,
&call_list);
client_setup_transport(&cs, transport, mdctx, &call_list);
GPR_ASSERT(f->client);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
grpc_chttp2_transport_start_reading(transport, NULL, 0, &call_list);
grpc_call_list_run(&call_list);
}
static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
grpc_channel_args *server_args) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_endpoint_pair *sfd = f->fixture_data;
grpc_mdctx *mdctx = grpc_mdctx_create();
grpc_transport *transport;
@ -129,9 +136,11 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
f->server = grpc_server_create_from_filters(NULL, 0, server_args);
grpc_server_register_completion_queue(f->server, f->cq, NULL);
grpc_server_start(f->server);
transport = grpc_create_chttp2_transport(server_args, sfd->server, mdctx, 0);
transport = grpc_create_chttp2_transport(server_args, sfd->server, mdctx, 0,
&call_list);
server_setup_transport(f, transport, mdctx);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
grpc_chttp2_transport_start_reading(transport, NULL, 0, &call_list);
grpc_call_list_run(&call_list);
}
static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) {

@ -63,9 +63,11 @@ static void server_setup_transport(void *ts, grpc_transport *transport,
grpc_end2end_test_fixture *f = ts;
static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter};
grpc_server_setup_transport(f->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx, g_workqueue,
grpc_server_get_channel_args(f->server));
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_server_setup_transport(
f->server, transport, extra_filters, GPR_ARRAY_SIZE(extra_filters), mdctx,
g_workqueue, grpc_server_get_channel_args(f->server), &call_list);
grpc_call_list_run(&call_list);
}
typedef struct {
@ -74,16 +76,17 @@ typedef struct {
} sp_client_setup;
static void client_setup_transport(void *ts, grpc_transport *transport,
grpc_mdctx *mdctx) {
grpc_mdctx *mdctx,
grpc_call_list *call_list) {
sp_client_setup *cs = ts;
const grpc_channel_filter *filters[] = {&grpc_http_client_filter,
&grpc_compress_filter,
&grpc_connected_channel_filter};
size_t nfilters = sizeof(filters) / sizeof(*filters);
grpc_channel *channel =
grpc_channel_create_from_filters("socketpair-target", filters, nfilters,
cs->client_args, mdctx, g_workqueue, 1);
grpc_channel *channel = grpc_channel_create_from_filters(
"socketpair-target", filters, nfilters, cs->client_args, mdctx,
g_workqueue, 1, call_list);
cs->f->client = channel;
@ -107,20 +110,24 @@ static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f,
grpc_channel_args *client_args) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_endpoint_pair *sfd = f->fixture_data;
grpc_transport *transport;
grpc_mdctx *mdctx = grpc_mdctx_create();
sp_client_setup cs;
cs.client_args = client_args;
cs.f = f;
transport = grpc_create_chttp2_transport(client_args, sfd->client, mdctx, 1);
client_setup_transport(&cs, transport, mdctx);
transport = grpc_create_chttp2_transport(client_args, sfd->client, mdctx, 1,
&call_list);
client_setup_transport(&cs, transport, mdctx, &call_list);
GPR_ASSERT(f->client);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
grpc_chttp2_transport_start_reading(transport, NULL, 0, &call_list);
grpc_call_list_run(&call_list);
}
static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
grpc_channel_args *server_args) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_endpoint_pair *sfd = f->fixture_data;
grpc_mdctx *mdctx = grpc_mdctx_create();
grpc_transport *transport;
@ -128,9 +135,11 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
f->server = grpc_server_create_from_filters(NULL, 0, server_args);
grpc_server_register_completion_queue(f->server, f->cq, NULL);
grpc_server_start(f->server);
transport = grpc_create_chttp2_transport(server_args, sfd->server, mdctx, 0);
transport = grpc_create_chttp2_transport(server_args, sfd->server, mdctx, 0,
&call_list);
server_setup_transport(f, transport, mdctx);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
grpc_chttp2_transport_start_reading(transport, NULL, 0, &call_list);
grpc_call_list_run(&call_list);
}
static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) {

@ -63,9 +63,11 @@ static void server_setup_transport(void *ts, grpc_transport *transport,
grpc_end2end_test_fixture *f = ts;
static grpc_channel_filter const *extra_filters[] = {
&grpc_http_server_filter};
grpc_server_setup_transport(f->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx, g_workqueue,
grpc_server_get_channel_args(f->server));
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_server_setup_transport(
f->server, transport, extra_filters, GPR_ARRAY_SIZE(extra_filters), mdctx,
g_workqueue, grpc_server_get_channel_args(f->server), &call_list);
grpc_call_list_run(&call_list);
}
typedef struct {
@ -74,16 +76,17 @@ typedef struct {
} sp_client_setup;
static void client_setup_transport(void *ts, grpc_transport *transport,
grpc_mdctx *mdctx) {
grpc_mdctx *mdctx,
grpc_call_list *call_list) {
sp_client_setup *cs = ts;
const grpc_channel_filter *filters[] = {&grpc_http_client_filter,
&grpc_compress_filter,
&grpc_connected_channel_filter};
size_t nfilters = sizeof(filters) / sizeof(*filters);
grpc_channel *channel =
grpc_channel_create_from_filters("socketpair-target", filters, nfilters,
cs->client_args, mdctx, g_workqueue, 1);
grpc_channel *channel = grpc_channel_create_from_filters(
"socketpair-target", filters, nfilters, cs->client_args, mdctx,
g_workqueue, 1, call_list);
cs->f->client = channel;
@ -107,20 +110,24 @@ static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
static void chttp2_init_client_socketpair(grpc_end2end_test_fixture *f,
grpc_channel_args *client_args) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_endpoint_pair *sfd = f->fixture_data;
grpc_transport *transport;
grpc_mdctx *mdctx = grpc_mdctx_create();
sp_client_setup cs;
cs.client_args = client_args;
cs.f = f;
transport = grpc_create_chttp2_transport(client_args, sfd->client, mdctx, 1);
client_setup_transport(&cs, transport, mdctx);
transport = grpc_create_chttp2_transport(client_args, sfd->client, mdctx, 1,
&call_list);
client_setup_transport(&cs, transport, mdctx, &call_list);
GPR_ASSERT(f->client);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
grpc_chttp2_transport_start_reading(transport, NULL, 0, &call_list);
grpc_call_list_run(&call_list);
}
static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
grpc_channel_args *server_args) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_endpoint_pair *sfd = f->fixture_data;
grpc_mdctx *mdctx = grpc_mdctx_create();
grpc_transport *transport;
@ -128,9 +135,11 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f,
f->server = grpc_server_create_from_filters(NULL, 0, server_args);
grpc_server_register_completion_queue(f->server, f->cq, NULL);
grpc_server_start(f->server);
transport = grpc_create_chttp2_transport(server_args, sfd->server, mdctx, 0);
transport = grpc_create_chttp2_transport(server_args, sfd->server, mdctx, 0,
&call_list);
server_setup_transport(f, transport, mdctx);
grpc_chttp2_transport_start_reading(transport, NULL, 0);
grpc_chttp2_transport_start_reading(transport, NULL, 0, &call_list);
grpc_call_list_run(&call_list);
}
static void chttp2_tear_down_socketpair(grpc_end2end_test_fixture *f) {

@ -53,7 +53,8 @@ static gpr_timespec n_seconds_time(int seconds) {
return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
}
static void on_finish(void *arg, const grpc_httpcli_response *response) {
static void on_finish(void *arg, const grpc_httpcli_response *response,
grpc_call_list *call_list) {
const char *expect =
"<html><head><title>Hello world!</title></head>"
"<body><p>This is a test</p></body></html>";
@ -71,6 +72,7 @@ static void on_finish(void *arg, const grpc_httpcli_response *response) {
static void test_get(int use_ssl, int port) {
grpc_httpcli_request req;
char *host;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
g_done = 0;
gpr_log(GPR_INFO, "running %s with use_ssl=%d.", "test_get", use_ssl);
@ -84,12 +86,15 @@ static void test_get(int use_ssl, int port) {
req.handshaker = use_ssl ? &grpc_httpcli_ssl : &grpc_httpcli_plaintext;
grpc_httpcli_get(&g_context, &g_pollset, &req, n_seconds_time(15), on_finish,
(void *)42);
(void *)42, &call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
while (!g_done) {
grpc_pollset_worker worker;
grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
n_seconds_time(20));
n_seconds_time(20), &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_call_list_run(&call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
gpr_free(host);
@ -98,6 +103,7 @@ static void test_get(int use_ssl, int port) {
static void test_post(int use_ssl, int port) {
grpc_httpcli_request req;
char *host;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
g_done = 0;
gpr_log(GPR_INFO, "running %s with use_ssl=%d.", "test_post", (int)use_ssl);
@ -111,20 +117,27 @@ static void test_post(int use_ssl, int port) {
req.handshaker = use_ssl ? &grpc_httpcli_ssl : &grpc_httpcli_plaintext;
grpc_httpcli_post(&g_context, &g_pollset, &req, "hello", 5,
n_seconds_time(15), on_finish, (void *)42);
n_seconds_time(15), on_finish, (void *)42, &call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
while (!g_done) {
grpc_pollset_worker worker;
grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
n_seconds_time(20));
n_seconds_time(20), &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_call_list_run(&call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
gpr_free(host);
}
static void destroy_pollset(void *ignored) { grpc_pollset_destroy(&g_pollset); }
static void destroy_pollset(void *p, int success, grpc_call_list *call_list) {
grpc_pollset_destroy(p);
}
int main(int argc, char **argv) {
grpc_closure destroyed;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_subprocess *server;
char *me = argv[0];
char *lslash = strrchr(me, '/');
@ -161,7 +174,9 @@ int main(int argc, char **argv) {
test_post(0, port);
grpc_httpcli_context_destroy(&g_context);
grpc_pollset_shutdown(&g_pollset, destroy_pollset, NULL);
grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
grpc_pollset_shutdown(&g_pollset, &destroyed, &call_list);
grpc_call_list_run(&call_list);
grpc_shutdown();
gpr_subprocess_destroy(server);

@ -42,11 +42,8 @@
#define MAX_CB 30
static int cb_called[MAX_CB][2];
static int kicks;
void grpc_kick_poller(void) { ++kicks; }
static void cb(void *arg, int success) {
static void cb(void *arg, int success, grpc_call_list *call_list) {
cb_called[(gpr_intptr)arg][success]++;
}
@ -54,6 +51,7 @@ static void add_test(void) {
gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
int i;
grpc_alarm alarms[20];
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_alarm_list_init(start);
memset(cb_called, 0, sizeof(cb_called));
@ -62,55 +60,56 @@ static void add_test(void) {
for (i = 0; i < 10; i++) {
grpc_alarm_init(&alarms[i],
gpr_time_add(start, gpr_time_from_millis(10, GPR_TIMESPAN)),
cb, (void *)(gpr_intptr)i, start);
cb, (void *)(gpr_intptr)i, start, &call_list);
}
/* 1010 ms alarms. will expire in the next epoch */
for (i = 10; i < 20; i++) {
grpc_alarm_init(&alarms[i], gpr_time_add(start, gpr_time_from_millis(
1010, GPR_TIMESPAN)),
cb, (void *)(gpr_intptr)i, start);
cb, (void *)(gpr_intptr)i, start, &call_list);
}
/* collect alarms. Only the first batch should be ready. */
GPR_ASSERT(10 == grpc_alarm_check(NULL,
gpr_time_add(start, gpr_time_from_millis(
GPR_ASSERT(10 == grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(
500, GPR_TIMESPAN)),
NULL));
NULL, &call_list));
grpc_call_list_run(&call_list);
for (i = 0; i < 20; i++) {
GPR_ASSERT(cb_called[i][1] == (i < 10));
GPR_ASSERT(cb_called[i][0] == 0);
}
GPR_ASSERT(0 == grpc_alarm_check(
NULL, gpr_time_add(
start, gpr_time_from_millis(600, GPR_TIMESPAN)),
NULL));
GPR_ASSERT(0 == grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(
600, GPR_TIMESPAN)),
NULL, &call_list));
grpc_call_list_run(&call_list);
for (i = 0; i < 30; i++) {
GPR_ASSERT(cb_called[i][1] == (i < 10));
GPR_ASSERT(cb_called[i][0] == 0);
}
/* collect the rest of the alarms */
GPR_ASSERT(
10 == grpc_alarm_check(NULL, gpr_time_add(start, gpr_time_from_millis(
1500, GPR_TIMESPAN)),
NULL));
GPR_ASSERT(10 ==
grpc_alarm_check(
gpr_time_add(start, gpr_time_from_millis(1500, GPR_TIMESPAN)),
NULL, &call_list));
grpc_call_list_run(&call_list);
for (i = 0; i < 30; i++) {
GPR_ASSERT(cb_called[i][1] == (i < 20));
GPR_ASSERT(cb_called[i][0] == 0);
}
GPR_ASSERT(0 == grpc_alarm_check(NULL,
gpr_time_add(start, gpr_time_from_millis(
GPR_ASSERT(0 == grpc_alarm_check(gpr_time_add(start, gpr_time_from_millis(
1600, GPR_TIMESPAN)),
NULL));
NULL, &call_list));
for (i = 0; i < 30; i++) {
GPR_ASSERT(cb_called[i][1] == (i < 20));
GPR_ASSERT(cb_called[i][0] == 0);
}
grpc_alarm_list_shutdown();
grpc_alarm_list_shutdown(&call_list);
grpc_call_list_run(&call_list);
}
static gpr_timespec tfm(int m) {
@ -122,28 +121,32 @@ static gpr_timespec tfm(int m) {
/* Cleaning up a list with pending alarms. */
void destruction_test(void) {
grpc_alarm alarms[5];
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_alarm_list_init(gpr_time_0(GPR_CLOCK_REALTIME));
memset(cb_called, 0, sizeof(cb_called));
grpc_alarm_init(&alarms[0], tfm(100), cb, (void *)(gpr_intptr)0,
gpr_time_0(GPR_CLOCK_REALTIME));
gpr_time_0(GPR_CLOCK_REALTIME), &call_list);
grpc_alarm_init(&alarms[1], tfm(3), cb, (void *)(gpr_intptr)1,
gpr_time_0(GPR_CLOCK_REALTIME));
gpr_time_0(GPR_CLOCK_REALTIME), &call_list);
grpc_alarm_init(&alarms[2], tfm(100), cb, (void *)(gpr_intptr)2,
gpr_time_0(GPR_CLOCK_REALTIME));
gpr_time_0(GPR_CLOCK_REALTIME), &call_list);
grpc_alarm_init(&alarms[3], tfm(3), cb, (void *)(gpr_intptr)3,
gpr_time_0(GPR_CLOCK_REALTIME));
gpr_time_0(GPR_CLOCK_REALTIME), &call_list);
grpc_alarm_init(&alarms[4], tfm(1), cb, (void *)(gpr_intptr)4,
gpr_time_0(GPR_CLOCK_REALTIME));
GPR_ASSERT(1 == grpc_alarm_check(NULL, tfm(2), NULL));
gpr_time_0(GPR_CLOCK_REALTIME), &call_list);
GPR_ASSERT(1 == grpc_alarm_check(tfm(2), NULL, &call_list));
grpc_call_list_run(&call_list);
GPR_ASSERT(1 == cb_called[4][1]);
grpc_alarm_cancel(&alarms[0]);
grpc_alarm_cancel(&alarms[3]);
grpc_alarm_cancel(&alarms[0], &call_list);
grpc_alarm_cancel(&alarms[3], &call_list);
grpc_call_list_run(&call_list);
GPR_ASSERT(1 == cb_called[0][0]);
GPR_ASSERT(1 == cb_called[3][0]);
grpc_alarm_list_shutdown();
grpc_alarm_list_shutdown(&call_list);
grpc_call_list_run(&call_list);
GPR_ASSERT(1 == cb_called[1][0]);
GPR_ASSERT(1 == cb_called[2][0]);
}

@ -65,7 +65,8 @@ typedef struct {
} alarm_arg;
/* Called when an alarm expires. */
static void alarm_cb(void *arg /* alarm_arg */, int success) {
static void alarm_cb(void *arg /* alarm_arg */, int success,
grpc_call_list *call_list) {
alarm_arg *a = arg;
gpr_mu_lock(&a->mu);
if (success) {
@ -90,6 +91,7 @@ static void test_grpc_alarm(void) {
*/
gpr_timespec alarm_deadline;
gpr_timespec followup_deadline;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
alarm_arg arg;
alarm_arg arg2;
@ -107,7 +109,7 @@ static void test_grpc_alarm(void) {
gpr_event_init(&arg.fcb_arg);
grpc_alarm_init(&alarm, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100), alarm_cb, &arg,
gpr_now(GPR_CLOCK_MONOTONIC));
gpr_now(GPR_CLOCK_MONOTONIC), &call_list);
alarm_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1);
gpr_mu_lock(&arg.mu);
@ -157,8 +159,8 @@ static void test_grpc_alarm(void) {
gpr_event_init(&arg2.fcb_arg);
grpc_alarm_init(&alarm_to_cancel, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100),
alarm_cb, &arg2, gpr_now(GPR_CLOCK_MONOTONIC));
grpc_alarm_cancel(&alarm_to_cancel);
alarm_cb, &arg2, gpr_now(GPR_CLOCK_MONOTONIC), &call_list);
grpc_alarm_cancel(&alarm_to_cancel, &call_list);
alarm_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1);
gpr_mu_lock(&arg2.mu);

@ -43,20 +43,20 @@
#include "test/core/iomgr/endpoint_tests.h"
static grpc_pollset g_pollset;
static grpc_workqueue *g_workqueue;
static void clean_up(void) {}
static grpc_endpoint_test_fixture create_fixture_endpoint_pair(
size_t slice_size) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_endpoint_test_fixture f;
grpc_endpoint_pair p =
grpc_iomgr_create_endpoint_pair("test", slice_size, g_workqueue);
grpc_endpoint_pair p = grpc_iomgr_create_endpoint_pair("test", slice_size);
f.client_ep = p.client;
f.server_ep = p.server;
grpc_endpoint_add_to_pollset(f.client_ep, &g_pollset);
grpc_endpoint_add_to_pollset(f.server_ep, &g_pollset);
grpc_endpoint_add_to_pollset(f.client_ep, &g_pollset, &call_list);
grpc_endpoint_add_to_pollset(f.server_ep, &g_pollset, &call_list);
grpc_call_list_run(&call_list);
return f;
}
@ -65,16 +65,20 @@ static grpc_endpoint_test_config configs[] = {
{"tcp/tcp_socketpair", create_fixture_endpoint_pair, clean_up},
};
static void destroy_pollset(void *p) { grpc_pollset_destroy(p); }
static void destroy_pollset(void *p, int success, grpc_call_list *call_list) {
grpc_pollset_destroy(p);
}
int main(int argc, char **argv) {
grpc_closure destroyed;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_test_init(argc, argv);
grpc_init();
grpc_pollset_init(&g_pollset);
g_workqueue = grpc_workqueue_create();
grpc_endpoint_tests(configs[0], &g_pollset);
grpc_pollset_shutdown(&g_pollset, destroy_pollset, &g_pollset);
GRPC_WORKQUEUE_UNREF(g_workqueue, "destroy");
grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
grpc_pollset_shutdown(&g_pollset, &destroyed, &call_list);
grpc_call_list_run(&call_list);
grpc_shutdown();
return 0;

@ -243,9 +243,10 @@ static void read_and_write_test(grpc_endpoint_test_config config,
grpc_pollset_worker worker;
GPR_ASSERT(gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) < 0);
grpc_pollset_work(g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
deadline);
deadline, &call_list);
}
gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
grpc_call_list_run(&call_list);
end_test(config);
gpr_slice_buffer_destroy(&state.outgoing);

@ -43,11 +43,9 @@ int main(int argc, char **argv) {
int i;
struct rlimit rlim;
grpc_endpoint_pair p;
grpc_workqueue *workqueue;
grpc_test_init(argc, argv);
grpc_iomgr_init();
workqueue = grpc_workqueue_create();
/* set max # of file descriptors to a low value, and
verify we can create and destroy many more than this number
@ -56,12 +54,13 @@ int main(int argc, char **argv) {
GPR_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &rlim));
for (i = 0; i < 100; i++) {
p = grpc_iomgr_create_endpoint_pair("test", 1, workqueue);
grpc_endpoint_destroy(p.client);
grpc_endpoint_destroy(p.server);
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
p = grpc_iomgr_create_endpoint_pair("test", 1);
grpc_endpoint_destroy(p.client, &call_list);
grpc_endpoint_destroy(p.server, &call_list);
grpc_call_list_run(&call_list);
}
GRPC_WORKQUEUE_UNREF(workqueue, "destroy");
grpc_iomgr_shutdown();
return 0;
}

@ -52,7 +52,6 @@
#include "test/core/util/test_config.h"
static grpc_pollset g_pollset;
static grpc_workqueue *g_workqueue;
/* buffer size used to send and receive data.
1024 is the minimal value to set TCP send and receive buffer. */
@ -119,18 +118,18 @@ typedef struct {
/* Called when an upload session can be safely shutdown.
Close session FD and start to shutdown listen FD. */
static void session_shutdown_cb(void *arg, /*session*/
int success) {
int success, grpc_call_list *call_list) {
session *se = arg;
server *sv = se->sv;
grpc_fd_orphan(se->em_fd, NULL, "a");
grpc_fd_orphan(se->em_fd, NULL, "a", call_list);
gpr_free(se);
/* Start to shutdown listen fd. */
grpc_fd_shutdown(sv->em_fd);
grpc_fd_shutdown(sv->em_fd, call_list);
}
/* Called when data become readable in a session. */
static void session_read_cb(void *arg, /*session*/
int success) {
int success, grpc_call_list *call_list) {
session *se = arg;
int fd = se->em_fd->fd;
@ -138,7 +137,7 @@ static void session_read_cb(void *arg, /*session*/
ssize_t read_total = 0;
if (!success) {
session_shutdown_cb(arg, 1);
session_shutdown_cb(arg, 1, call_list);
return;
}
@ -153,7 +152,7 @@ static void session_read_cb(void *arg, /*session*/
It is possible to read nothing due to spurious edge event or data has
been drained, In such a case, read() returns -1 and set errno to EAGAIN. */
if (read_once == 0) {
session_shutdown_cb(arg, 1);
session_shutdown_cb(arg, 1, call_list);
} else if (read_once == -1) {
if (errno == EAGAIN) {
/* An edge triggered event is cached in the kernel until next poll.
@ -164,7 +163,7 @@ static void session_read_cb(void *arg, /*session*/
TODO(chenw): in multi-threaded version, callback and polling can be
run in different threads. polling may catch a persist read edge event
before notify_on_read is called. */
grpc_fd_notify_on_read(se->em_fd, &se->session_read_closure);
grpc_fd_notify_on_read(se->em_fd, &se->session_read_closure, call_list);
} else {
gpr_log(GPR_ERROR, "Unhandled read error %s", strerror(errno));
abort();
@ -174,10 +173,11 @@ static void session_read_cb(void *arg, /*session*/
/* Called when the listen FD can be safely shutdown.
Close listen FD and signal that server can be shutdown. */
static void listen_shutdown_cb(void *arg /*server*/, int success) {
static void listen_shutdown_cb(void *arg /*server*/, int success,
grpc_call_list *call_list) {
server *sv = arg;
grpc_fd_orphan(sv->em_fd, NULL, "b");
grpc_fd_orphan(sv->em_fd, NULL, "b", call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
sv->done = 1;
@ -187,7 +187,7 @@ static void listen_shutdown_cb(void *arg /*server*/, int success) {
/* Called when a new TCP connection request arrives in the listening port. */
static void listen_cb(void *arg, /*=sv_arg*/
int success) {
int success, grpc_call_list *call_list) {
server *sv = arg;
int fd;
int flags;
@ -197,7 +197,7 @@ static void listen_cb(void *arg, /*=sv_arg*/
grpc_fd *listen_em_fd = sv->em_fd;
if (!success) {
listen_shutdown_cb(arg, 1);
listen_shutdown_cb(arg, 1, call_list);
return;
}
@ -208,13 +208,13 @@ static void listen_cb(void *arg, /*=sv_arg*/
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
se = gpr_malloc(sizeof(*se));
se->sv = sv;
se->em_fd = grpc_fd_create(fd, g_workqueue, "listener");
grpc_pollset_add_fd(&g_pollset, se->em_fd);
se->em_fd = grpc_fd_create(fd, "listener");
grpc_pollset_add_fd(&g_pollset, se->em_fd, call_list);
se->session_read_closure.cb = session_read_cb;
se->session_read_closure.cb_arg = se;
grpc_fd_notify_on_read(se->em_fd, &se->session_read_closure);
grpc_fd_notify_on_read(se->em_fd, &se->session_read_closure, call_list);
grpc_fd_notify_on_read(listen_em_fd, &sv->listen_closure);
grpc_fd_notify_on_read(listen_em_fd, &sv->listen_closure, call_list);
}
/* Max number of connections pending to be accepted by listen(). */
@ -224,7 +224,7 @@ static void listen_cb(void *arg, /*=sv_arg*/
listen_cb() is registered to be interested in reading from listen_fd.
When connection request arrives, listen_cb() is called to accept the
connection request. */
static int server_start(server *sv) {
static int server_start(server *sv, grpc_call_list *call_list) {
int port = 0;
int fd;
struct sockaddr_in sin;
@ -237,12 +237,12 @@ static int server_start(server *sv) {
port = ntohs(sin.sin_port);
GPR_ASSERT(listen(fd, MAX_NUM_FD) == 0);
sv->em_fd = grpc_fd_create(fd, g_workqueue, "server");
grpc_pollset_add_fd(&g_pollset, sv->em_fd);
sv->em_fd = grpc_fd_create(fd, "server");
grpc_pollset_add_fd(&g_pollset, sv->em_fd, call_list);
/* Register to be interested in reading from listen_fd. */
sv->listen_closure.cb = listen_cb;
sv->listen_closure.cb_arg = sv;
grpc_fd_notify_on_read(sv->em_fd, &sv->listen_closure);
grpc_fd_notify_on_read(sv->em_fd, &sv->listen_closure, call_list);
return port;
}
@ -251,9 +251,13 @@ static int server_start(server *sv) {
static void server_wait_and_shutdown(server *sv) {
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
while (!sv->done) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_pollset_worker worker;
grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
gpr_inf_future(GPR_CLOCK_MONOTONIC));
gpr_inf_future(GPR_CLOCK_MONOTONIC), &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_call_list_run(&call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
}
@ -286,23 +290,24 @@ static void client_init(client *cl) {
}
/* Called when a client upload session is ready to shutdown. */
static void client_session_shutdown_cb(void *arg /*client*/, int success) {
static void client_session_shutdown_cb(void *arg /*client*/, int success,
grpc_call_list *call_list) {
client *cl = arg;
grpc_fd_orphan(cl->em_fd, NULL, "c");
grpc_fd_orphan(cl->em_fd, NULL, "c", call_list);
cl->done = 1;
grpc_pollset_kick(&g_pollset, NULL);
}
/* Write as much as possible, then register notify_on_write. */
static void client_session_write(void *arg, /*client*/
int success) {
int success, grpc_call_list *call_list) {
client *cl = arg;
int fd = cl->em_fd->fd;
ssize_t write_once = 0;
if (!success) {
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
client_session_shutdown_cb(arg, 1);
client_session_shutdown_cb(arg, 1, call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
return;
}
@ -317,10 +322,10 @@ static void client_session_write(void *arg, /*client*/
if (cl->client_write_cnt < CLIENT_TOTAL_WRITE_CNT) {
cl->write_closure.cb = client_session_write;
cl->write_closure.cb_arg = cl;
grpc_fd_notify_on_write(cl->em_fd, &cl->write_closure);
grpc_fd_notify_on_write(cl->em_fd, &cl->write_closure, call_list);
cl->client_write_cnt++;
} else {
client_session_shutdown_cb(arg, 1);
client_session_shutdown_cb(arg, 1, call_list);
}
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
} else {
@ -330,7 +335,7 @@ static void client_session_write(void *arg, /*client*/
}
/* Start a client to send a stream of bytes. */
static void client_start(client *cl, int port) {
static void client_start(client *cl, int port, grpc_call_list *call_list) {
int fd;
struct sockaddr_in sin;
create_test_socket(port, &fd, &sin);
@ -350,10 +355,10 @@ static void client_start(client *cl, int port) {
}
}
cl->em_fd = grpc_fd_create(fd, g_workqueue, "client");
grpc_pollset_add_fd(&g_pollset, cl->em_fd);
cl->em_fd = grpc_fd_create(fd, "client");
grpc_pollset_add_fd(&g_pollset, cl->em_fd, call_list);
client_session_write(cl, 1);
client_session_write(cl, 1, call_list);
}
/* Wait for the signal to shutdown a client. */
@ -361,8 +366,12 @@ static void client_wait_and_shutdown(client *cl) {
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
while (!cl->done) {
grpc_pollset_worker worker;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
gpr_inf_future(GPR_CLOCK_MONOTONIC));
gpr_inf_future(GPR_CLOCK_MONOTONIC), &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_call_list_run(&call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
}
@ -374,11 +383,13 @@ static void test_grpc_fd(void) {
server sv;
client cl;
int port;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
server_init(&sv);
port = server_start(&sv);
port = server_start(&sv, &call_list);
client_init(&cl);
client_start(&cl, port);
client_start(&cl, port, &call_list);
grpc_call_list_run(&call_list);
client_wait_and_shutdown(&cl);
server_wait_and_shutdown(&sv);
GPR_ASSERT(sv.read_bytes_total == cl.write_bytes_total);
@ -386,14 +397,15 @@ static void test_grpc_fd(void) {
}
typedef struct fd_change_data {
void (*cb_that_ran)(void *, int success);
void (*cb_that_ran)(void *, int success, grpc_call_list *call_list);
} fd_change_data;
void init_change_data(fd_change_data *fdc) { fdc->cb_that_ran = NULL; }
void destroy_change_data(fd_change_data *fdc) {}
static void first_read_callback(void *arg /* fd_change_data */, int success) {
static void first_read_callback(void *arg /* fd_change_data */, int success,
grpc_call_list *call_list) {
fd_change_data *fdc = arg;
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
@ -402,7 +414,8 @@ static void first_read_callback(void *arg /* fd_change_data */, int success) {
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
}
static void second_read_callback(void *arg /* fd_change_data */, int success) {
static void second_read_callback(void *arg /* fd_change_data */, int success,
grpc_call_list *call_list) {
fd_change_data *fdc = arg;
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
@ -424,6 +437,7 @@ static void test_grpc_fd_change(void) {
ssize_t result;
grpc_closure first_closure;
grpc_closure second_closure;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
first_closure.cb = first_read_callback;
first_closure.cb_arg = &a;
@ -439,11 +453,11 @@ static void test_grpc_fd_change(void) {
flags = fcntl(sv[1], F_GETFL, 0);
GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
em_fd = grpc_fd_create(sv[0], g_workqueue, "test_grpc_fd_change");
grpc_pollset_add_fd(&g_pollset, em_fd);
em_fd = grpc_fd_create(sv[0], "test_grpc_fd_change");
grpc_pollset_add_fd(&g_pollset, em_fd, &call_list);
/* Register the first callback, then make its FD readable */
grpc_fd_notify_on_read(em_fd, &first_closure);
grpc_fd_notify_on_read(em_fd, &first_closure, &call_list);
data = 0;
result = write(sv[1], &data, 1);
GPR_ASSERT(result == 1);
@ -453,7 +467,10 @@ static void test_grpc_fd_change(void) {
while (a.cb_that_ran == NULL) {
grpc_pollset_worker worker;
grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
gpr_inf_future(GPR_CLOCK_MONOTONIC));
gpr_inf_future(GPR_CLOCK_MONOTONIC), &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_call_list_run(&call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
}
GPR_ASSERT(a.cb_that_ran == first_read_callback);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
@ -464,7 +481,7 @@ static void test_grpc_fd_change(void) {
/* Now register a second callback with distinct change data, and do the same
thing again. */
grpc_fd_notify_on_read(em_fd, &second_closure);
grpc_fd_notify_on_read(em_fd, &second_closure, &call_list);
data = 0;
result = write(sv[1], &data, 1);
GPR_ASSERT(result == 1);
@ -473,29 +490,37 @@ static void test_grpc_fd_change(void) {
while (b.cb_that_ran == NULL) {
grpc_pollset_worker worker;
grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
gpr_inf_future(GPR_CLOCK_MONOTONIC));
gpr_inf_future(GPR_CLOCK_MONOTONIC), &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_call_list_run(&call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
}
/* Except now we verify that second_read_callback ran instead */
GPR_ASSERT(b.cb_that_ran == second_read_callback);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_fd_orphan(em_fd, NULL, "d");
grpc_fd_orphan(em_fd, NULL, "d", &call_list);
grpc_call_list_run(&call_list);
destroy_change_data(&a);
destroy_change_data(&b);
close(sv[1]);
}
static void destroy_pollset(void *p) { grpc_pollset_destroy(p); }
static void destroy_pollset(void *p, int success, grpc_call_list *call_list) {
grpc_pollset_destroy(p);
}
int main(int argc, char **argv) {
grpc_closure destroyed;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_test_init(argc, argv);
grpc_iomgr_init();
grpc_pollset_init(&g_pollset);
g_workqueue = grpc_workqueue_create();
test_grpc_fd();
test_grpc_fd_change();
grpc_pollset_shutdown(&g_pollset, destroy_pollset, &g_pollset);
GRPC_WORKQUEUE_UNREF(g_workqueue, "destroy");
grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
grpc_pollset_shutdown(&g_pollset, &destroyed, &call_list);
grpc_call_list_run(&call_list);
grpc_iomgr_shutdown();
return 0;
}

@ -42,14 +42,16 @@ static gpr_timespec test_deadline(void) {
return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(100);
}
static void must_succeed(void* evp, grpc_resolved_addresses* p) {
static void must_succeed(void* evp, grpc_resolved_addresses* p,
grpc_call_list* call_list) {
GPR_ASSERT(p);
GPR_ASSERT(p->naddrs >= 1);
grpc_resolved_addresses_destroy(p);
gpr_event_set(evp, (void*)1);
}
static void must_fail(void* evp, grpc_resolved_addresses* p) {
static void must_fail(void* evp, grpc_resolved_addresses* p,
grpc_call_list* call_list) {
GPR_ASSERT(!p);
gpr_event_set(evp, (void*)1);
}

@ -49,8 +49,8 @@
static grpc_pollset_set g_pollset_set;
static grpc_pollset g_pollset;
static grpc_workqueue *g_workqueue;
static int g_connections_complete = 0;
static grpc_endpoint *g_connecting = NULL;
static gpr_timespec test_deadline(void) {
return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
@ -63,15 +63,18 @@ static void finish_connection() {
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
}
static void must_succeed(void *arg, grpc_endpoint *tcp) {
GPR_ASSERT(tcp);
grpc_endpoint_shutdown(tcp);
grpc_endpoint_destroy(tcp);
static void must_succeed(void *arg, int success, grpc_call_list *call_list) {
GPR_ASSERT(g_connecting != NULL);
GPR_ASSERT(success);
grpc_endpoint_shutdown(g_connecting, call_list);
grpc_endpoint_destroy(g_connecting, call_list);
g_connecting = NULL;
finish_connection();
}
static void must_fail(void *arg, grpc_endpoint *tcp) {
GPR_ASSERT(!tcp);
static void must_fail(void *arg, int success, grpc_call_list *call_list) {
GPR_ASSERT(g_connecting == NULL);
GPR_ASSERT(!success);
finish_connection();
}
@ -81,6 +84,8 @@ void test_succeeds(void) {
int svr_fd;
int r;
int connections_complete_before;
grpc_closure done;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_log(GPR_DEBUG, "test_succeeds");
@ -99,9 +104,10 @@ void test_succeeds(void) {
/* connect to it */
GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0);
grpc_tcp_client_connect(must_succeed, NULL, &g_pollset_set, g_workqueue,
grpc_closure_init(&done, must_succeed, NULL);
grpc_tcp_client_connect(&done, &g_connecting, &g_pollset_set,
(struct sockaddr *)&addr, addr_len,
gpr_inf_future(GPR_CLOCK_REALTIME));
gpr_inf_future(GPR_CLOCK_REALTIME), &call_list);
/* await the connection */
do {
@ -116,7 +122,10 @@ void test_succeeds(void) {
while (g_connections_complete == connections_complete_before) {
grpc_pollset_worker worker;
grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5));
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_call_list_run(&call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
@ -126,6 +135,8 @@ void test_fails(void) {
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
int connections_complete_before;
grpc_closure done;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_log(GPR_DEBUG, "test_fails");
@ -137,9 +148,10 @@ void test_fails(void) {
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
/* connect to a broken address */
grpc_tcp_client_connect(must_fail, NULL, &g_pollset_set, g_workqueue,
grpc_closure_init(&done, must_fail, NULL);
grpc_tcp_client_connect(&done, &g_connecting, &g_pollset_set,
(struct sockaddr *)&addr, addr_len,
gpr_inf_future(GPR_CLOCK_REALTIME));
gpr_inf_future(GPR_CLOCK_REALTIME), &call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
@ -147,7 +159,10 @@ void test_fails(void) {
while (g_connections_complete == connections_complete_before) {
grpc_pollset_worker worker;
grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
test_deadline());
test_deadline(), &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_call_list_run(&call_list);
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
@ -163,6 +178,8 @@ void test_times_out(void) {
int r;
int connections_complete_before;
gpr_timespec connect_deadline;
grpc_closure done;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_log(GPR_DEBUG, "test_times_out");
@ -196,8 +213,10 @@ void test_times_out(void) {
connections_complete_before = g_connections_complete;
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_tcp_client_connect(must_fail, NULL, &g_pollset_set, g_workqueue,
(struct sockaddr *)&addr, addr_len, connect_deadline);
grpc_closure_init(&done, must_fail, NULL);
grpc_tcp_client_connect(&done, &g_connecting, &g_pollset_set,
(struct sockaddr *)&addr, addr_len, connect_deadline,
&call_list);
/* Make sure the event doesn't trigger early */
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
@ -222,7 +241,10 @@ void test_times_out(void) {
connections_complete_before + is_after_deadline);
}
grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10));
GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10), &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
grpc_call_list_run(&call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
@ -232,22 +254,27 @@ void test_times_out(void) {
}
}
static void destroy_pollset(void *p) { grpc_pollset_destroy(p); }
static void destroy_pollset(void *p, int success, grpc_call_list *call_list) {
grpc_pollset_destroy(p);
}
int main(int argc, char **argv) {
grpc_closure destroyed;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_test_init(argc, argv);
grpc_init();
grpc_pollset_set_init(&g_pollset_set);
grpc_pollset_init(&g_pollset);
grpc_pollset_set_add_pollset(&g_pollset_set, &g_pollset);
g_workqueue = grpc_workqueue_create();
grpc_pollset_set_add_pollset(&g_pollset_set, &g_pollset, &call_list);
grpc_call_list_run(&call_list);
test_succeeds();
gpr_log(GPR_ERROR, "End of first test");
test_fails();
test_times_out();
grpc_pollset_set_destroy(&g_pollset_set);
grpc_pollset_shutdown(&g_pollset, destroy_pollset, &g_pollset);
GRPC_WORKQUEUE_UNREF(g_workqueue, "destroy");
grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
grpc_pollset_shutdown(&g_pollset, &destroyed, &call_list);
grpc_call_list_run(&call_list);
grpc_shutdown();
return 0;
}

@ -318,7 +318,8 @@ static void check_metadata(expected_md *expected, grpc_credentials_md *md_elems,
static void check_google_iam_metadata(void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status) {
grpc_credentials_status status,
grpc_call_list *call_list) {
grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
test_google_iam_authorization_token},
@ -331,19 +332,23 @@ static void check_google_iam_metadata(void *user_data,
}
static void test_google_iam_creds(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *creds = grpc_google_iam_credentials_create(
test_google_iam_authorization_token, test_google_iam_authority_selector,
NULL);
GPR_ASSERT(grpc_credentials_has_request_metadata(creds));
GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds));
grpc_credentials_get_request_metadata(creds, NULL, test_service_url,
check_google_iam_metadata, creds);
check_google_iam_metadata, creds,
&call_list);
grpc_call_list_run(&call_list);
}
static void check_access_token_metadata(void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status) {
grpc_credentials_status status,
grpc_call_list *call_list) {
grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
@ -353,17 +358,22 @@ static void check_access_token_metadata(void *user_data,
}
static void test_access_token_creds(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *creds = grpc_access_token_credentials_create("blah", NULL);
GPR_ASSERT(grpc_credentials_has_request_metadata(creds));
GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds));
GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_OAUTH2) == 0);
grpc_credentials_get_request_metadata(creds, NULL, test_service_url,
check_access_token_metadata, creds);
check_access_token_metadata, creds,
&call_list);
grpc_call_list_run(&call_list);
}
static void check_ssl_oauth2_composite_metadata(
void *user_data, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) {
static void check_ssl_oauth2_composite_metadata(void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status,
grpc_call_list *call_list) {
grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = {
{GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token}};
@ -374,6 +384,7 @@ static void check_ssl_oauth2_composite_metadata(
}
static void test_ssl_oauth2_composite_creds(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *ssl_creds =
grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
const grpc_credentials_array *creds_array;
@ -395,7 +406,8 @@ static void test_ssl_oauth2_composite_creds(void) {
GRPC_CREDENTIALS_TYPE_OAUTH2) == 0);
grpc_credentials_get_request_metadata(composite_creds, NULL, test_service_url,
check_ssl_oauth2_composite_metadata,
composite_creds);
composite_creds, &call_list);
grpc_call_list_run(&call_list);
}
void test_ssl_fake_transport_security_composite_creds_failure(void) {
@ -412,7 +424,7 @@ void test_ssl_fake_transport_security_composite_creds_failure(void) {
static void check_ssl_oauth2_google_iam_composite_metadata(
void *user_data, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) {
grpc_credentials_status status, grpc_call_list *call_list) {
grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = {
{GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token},
@ -427,6 +439,7 @@ static void check_ssl_oauth2_google_iam_composite_metadata(
}
static void test_ssl_oauth2_google_iam_composite_creds(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *ssl_creds =
grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
const grpc_credentials_array *creds_array;
@ -457,12 +470,16 @@ static void test_ssl_oauth2_google_iam_composite_creds(void) {
GRPC_CREDENTIALS_TYPE_IAM) == 0);
grpc_credentials_get_request_metadata(
composite_creds, NULL, test_service_url,
check_ssl_oauth2_google_iam_composite_metadata, composite_creds);
check_ssl_oauth2_google_iam_composite_metadata, composite_creds,
&call_list);
grpc_call_list_run(&call_list);
}
static void on_oauth2_creds_get_metadata_success(
void *user_data, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) {
static void on_oauth2_creds_get_metadata_success(void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status,
grpc_call_list *call_list) {
GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
GPR_ASSERT(num_md == 1);
GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "Authorization") == 0);
@ -473,9 +490,11 @@ static void on_oauth2_creds_get_metadata_success(
GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0);
}
static void on_oauth2_creds_get_metadata_failure(
void *user_data, grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) {
static void on_oauth2_creds_get_metadata_failure(void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status,
grpc_call_list *call_list) {
GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR);
GPR_ASSERT(num_md == 0);
GPR_ASSERT(user_data != NULL);
@ -497,39 +516,44 @@ static void validate_compute_engine_http_request(
static int compute_engine_httpcli_get_success_override(
const grpc_httpcli_request *request, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
grpc_httpcli_response_cb on_response, void *user_data,
grpc_call_list *call_list) {
grpc_httpcli_response response =
http_response(200, valid_oauth2_json_response);
validate_compute_engine_http_request(request);
on_response(user_data, &response);
on_response(user_data, &response, call_list);
return 1;
}
static int compute_engine_httpcli_get_failure_override(
const grpc_httpcli_request *request, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
grpc_httpcli_response_cb on_response, void *user_data,
grpc_call_list *call_list) {
grpc_httpcli_response response = http_response(403, "Not Authorized.");
validate_compute_engine_http_request(request);
on_response(user_data, &response);
on_response(user_data, &response, call_list);
return 1;
}
static int httpcli_post_should_not_be_called(
const grpc_httpcli_request *request, const char *body_bytes,
size_t body_size, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
grpc_httpcli_response_cb on_response, void *user_data,
grpc_call_list *call_list) {
GPR_ASSERT("HTTP POST should not be called" == NULL);
return 1;
}
static int httpcli_get_should_not_be_called(
const grpc_httpcli_request *request, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
grpc_httpcli_response_cb on_response, void *user_data,
grpc_call_list *call_list) {
GPR_ASSERT("HTTP GET should not be called" == NULL);
return 1;
}
static void test_compute_engine_creds_success(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *compute_engine_creds =
grpc_google_compute_engine_credentials_create(NULL);
GPR_ASSERT(grpc_credentials_has_request_metadata(compute_engine_creds));
@ -540,20 +564,23 @@ static void test_compute_engine_creds_success(void) {
httpcli_post_should_not_be_called);
grpc_credentials_get_request_metadata(
compute_engine_creds, NULL, test_service_url,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
on_oauth2_creds_get_metadata_success, (void *)test_user_data, &call_list);
grpc_call_list_run(&call_list);
/* Second request: the cached token should be served directly. */
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
grpc_credentials_get_request_metadata(
compute_engine_creds, NULL, test_service_url,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
on_oauth2_creds_get_metadata_success, (void *)test_user_data, &call_list);
grpc_call_list_run(&call_list);
grpc_credentials_unref(compute_engine_creds);
grpc_httpcli_set_override(NULL, NULL);
}
static void test_compute_engine_creds_failure(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *compute_engine_creds =
grpc_google_compute_engine_credentials_create(NULL);
grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override,
@ -562,9 +589,10 @@ static void test_compute_engine_creds_failure(void) {
GPR_ASSERT(grpc_credentials_has_request_metadata_only(compute_engine_creds));
grpc_credentials_get_request_metadata(
compute_engine_creds, NULL, test_service_url,
on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
on_oauth2_creds_get_metadata_failure, (void *)test_user_data, &call_list);
grpc_credentials_unref(compute_engine_creds);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
static void validate_refresh_token_http_request(
@ -592,25 +620,26 @@ static void validate_refresh_token_http_request(
static int refresh_token_httpcli_post_success(
const grpc_httpcli_request *request, const char *body, size_t body_size,
gpr_timespec deadline, grpc_httpcli_response_cb on_response,
void *user_data) {
void *user_data, grpc_call_list *call_list) {
grpc_httpcli_response response =
http_response(200, valid_oauth2_json_response);
validate_refresh_token_http_request(request, body, body_size);
on_response(user_data, &response);
on_response(user_data, &response, call_list);
return 1;
}
static int refresh_token_httpcli_post_failure(
const grpc_httpcli_request *request, const char *body, size_t body_size,
gpr_timespec deadline, grpc_httpcli_response_cb on_response,
void *user_data) {
void *user_data, grpc_call_list *call_list) {
grpc_httpcli_response response = http_response(403, "Not Authorized.");
validate_refresh_token_http_request(request, body, body_size);
on_response(user_data, &response);
on_response(user_data, &response, call_list);
return 1;
}
static void test_refresh_token_creds_success(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *refresh_token_creds =
grpc_google_refresh_token_credentials_create(test_refresh_token_str,
NULL);
@ -622,20 +651,24 @@ static void test_refresh_token_creds_success(void) {
refresh_token_httpcli_post_success);
grpc_credentials_get_request_metadata(
refresh_token_creds, NULL, test_service_url,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
on_oauth2_creds_get_metadata_success, (void *)test_user_data, &call_list);
grpc_call_list_run(&call_list);
/* Second request: the cached token should be served directly. */
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
grpc_credentials_get_request_metadata(
refresh_token_creds, NULL, test_service_url,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
on_oauth2_creds_get_metadata_success, (void *)test_user_data, &call_list);
grpc_call_list_run(&call_list);
grpc_credentials_unref(refresh_token_creds);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
static void test_refresh_token_creds_failure(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *refresh_token_creds =
grpc_google_refresh_token_credentials_create(test_refresh_token_str,
NULL);
@ -645,9 +678,10 @@ static void test_refresh_token_creds_failure(void) {
GPR_ASSERT(grpc_credentials_has_request_metadata_only(refresh_token_creds));
grpc_credentials_get_request_metadata(
refresh_token_creds, NULL, test_service_url,
on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
on_oauth2_creds_get_metadata_failure, (void *)test_user_data, &call_list);
grpc_credentials_unref(refresh_token_creds);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
static void validate_jwt_encode_and_sign_params(
@ -698,7 +732,8 @@ static char *encode_and_sign_jwt_should_not_be_called(
static void on_jwt_creds_get_metadata_success(void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status) {
grpc_credentials_status status,
grpc_call_list *call_list) {
char *expected_md_value;
gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt);
GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
@ -713,7 +748,8 @@ static void on_jwt_creds_get_metadata_success(void *user_data,
static void on_jwt_creds_get_metadata_failure(void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status) {
grpc_credentials_status status,
grpc_call_list *call_list) {
GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR);
GPR_ASSERT(num_md == 0);
GPR_ASSERT(user_data != NULL);
@ -722,6 +758,7 @@ static void on_jwt_creds_get_metadata_failure(void *user_data,
static void test_jwt_creds_success(void) {
char *json_key_string = test_json_key_str();
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *jwt_creds =
grpc_service_account_jwt_access_credentials_create(
json_key_string, grpc_max_auth_token_lifetime, NULL);
@ -732,21 +769,24 @@ static void test_jwt_creds_success(void) {
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
grpc_credentials_get_request_metadata(jwt_creds, NULL, test_service_url,
on_jwt_creds_get_metadata_success,
(void *)test_user_data);
(void *)test_user_data, &call_list);
grpc_call_list_run(&call_list);
/* Second request: the cached token should be served directly. */
grpc_jwt_encode_and_sign_set_override(
encode_and_sign_jwt_should_not_be_called);
grpc_credentials_get_request_metadata(jwt_creds, NULL, test_service_url,
on_jwt_creds_get_metadata_success,
(void *)test_user_data);
(void *)test_user_data, &call_list);
grpc_call_list_run(&call_list);
/* Third request: Different service url so jwt_encode_and_sign should be
called again (no caching). */
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
grpc_credentials_get_request_metadata(jwt_creds, NULL, other_test_service_url,
on_jwt_creds_get_metadata_success,
(void *)test_user_data);
(void *)test_user_data, &call_list);
grpc_call_list_run(&call_list);
gpr_free(json_key_string);
grpc_credentials_unref(jwt_creds);
@ -755,6 +795,7 @@ static void test_jwt_creds_success(void) {
static void test_jwt_creds_signing_failure(void) {
char *json_key_string = test_json_key_str();
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *jwt_creds =
grpc_service_account_jwt_access_credentials_create(
json_key_string, grpc_max_auth_token_lifetime, NULL);
@ -764,11 +805,12 @@ static void test_jwt_creds_signing_failure(void) {
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
grpc_credentials_get_request_metadata(jwt_creds, NULL, test_service_url,
on_jwt_creds_get_metadata_failure,
(void *)test_user_data);
(void *)test_user_data, &call_list);
gpr_free(json_key_string);
grpc_credentials_unref(jwt_creds);
grpc_jwt_encode_and_sign_set_override(NULL);
grpc_call_list_run(&call_list);
}
static void set_google_default_creds_env_var_with_file_contents(

@ -276,14 +276,16 @@ static grpc_httpcli_response http_response(int status, char *body) {
static int httpcli_post_should_not_be_called(
const grpc_httpcli_request *request, const char *body_bytes,
size_t body_size, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
grpc_httpcli_response_cb on_response, void *user_data,
grpc_call_list *call_list) {
GPR_ASSERT("HTTP POST should not be called" == NULL);
return 1;
}
static int httpcli_get_google_keys_for_email(
const grpc_httpcli_request *request, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
grpc_httpcli_response_cb on_response, void *user_data,
grpc_call_list *call_list) {
grpc_httpcli_response response = http_response(200, good_google_email_keys());
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
@ -291,7 +293,7 @@ static int httpcli_get_google_keys_for_email(
"/robot/v1/metadata/x509/"
"777-abaslkan11hlb6nmim3bpspl31ud@developer."
"gserviceaccount.com") == 0);
on_response(user_data, &response);
on_response(user_data, &response, call_list);
gpr_free(response.body);
return 1;
}
@ -307,6 +309,7 @@ static void on_verification_success(void *user_data,
}
static void test_jwt_verifier_google_email_issuer_success(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer);
@ -320,25 +323,29 @@ static void test_jwt_verifier_google_email_issuer_success(void) {
grpc_auth_json_key_destruct(&key);
GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
on_verification_success, (void *)expected_user_data);
on_verification_success, (void *)expected_user_data,
&call_list);
gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
static int httpcli_get_custom_keys_for_email(
const grpc_httpcli_request *request, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
grpc_httpcli_response_cb on_response, void *user_data,
grpc_call_list *call_list) {
grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
GPR_ASSERT(strcmp(request->host, "keys.bar.com") == 0);
GPR_ASSERT(strcmp(request->path, "/jwk/foo@bar.com") == 0);
on_response(user_data, &response);
on_response(user_data, &response, call_list);
gpr_free(response.body);
return 1;
}
static void test_jwt_verifier_custom_email_issuer_success(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(&custom_mapping, 1);
char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_custom_email_issuer);
@ -352,21 +359,23 @@ static void test_jwt_verifier_custom_email_issuer_success(void) {
grpc_auth_json_key_destruct(&key);
GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
on_verification_success, (void *)expected_user_data);
on_verification_success, (void *)expected_user_data,
&call_list);
gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
static int httpcli_get_jwk_set(const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response,
void *user_data) {
void *user_data, grpc_call_list *call_list) {
grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
GPR_ASSERT(strcmp(request->path, "/oauth2/v3/certs") == 0);
on_response(user_data, &response);
on_response(user_data, &response, call_list);
gpr_free(response.body);
return 1;
}
@ -374,7 +383,8 @@ static int httpcli_get_jwk_set(const grpc_httpcli_request *request,
static int httpcli_get_openid_config(const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response,
void *user_data) {
void *user_data,
grpc_call_list *call_list) {
grpc_httpcli_response response =
http_response(200, gpr_strdup(good_openid_config));
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
@ -382,12 +392,13 @@ static int httpcli_get_openid_config(const grpc_httpcli_request *request,
GPR_ASSERT(strcmp(request->path, GRPC_OPENID_CONFIG_URL_SUFFIX) == 0);
grpc_httpcli_set_override(httpcli_get_jwk_set,
httpcli_post_should_not_be_called);
on_response(user_data, &response);
on_response(user_data, &response, call_list);
gpr_free(response.body);
return 1;
}
static void test_jwt_verifier_url_issuer_success(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_url_issuer);
@ -401,10 +412,12 @@ static void test_jwt_verifier_url_issuer_success(void) {
grpc_auth_json_key_destruct(&key);
GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
on_verification_success, (void *)expected_user_data);
on_verification_success, (void *)expected_user_data,
&call_list);
gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
static void on_verification_key_retrieval_error(void *user_data,
@ -418,16 +431,17 @@ static void on_verification_key_retrieval_error(void *user_data,
static int httpcli_get_bad_json(const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response,
void *user_data) {
void *user_data, grpc_call_list *call_list) {
grpc_httpcli_response response =
http_response(200, gpr_strdup("{\"bad\": \"stuff\"}"));
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
on_response(user_data, &response);
on_response(user_data, &response, call_list);
gpr_free(response.body);
return 1;
}
static void test_jwt_verifier_url_issuer_bad_config(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_url_issuer);
@ -442,13 +456,15 @@ static void test_jwt_verifier_url_issuer_bad_config(void) {
GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
on_verification_key_retrieval_error,
(void *)expected_user_data);
(void *)expected_user_data, &call_list);
gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
static void test_jwt_verifier_bad_json_key(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer);
@ -463,10 +479,11 @@ static void test_jwt_verifier_bad_json_key(void) {
GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
on_verification_key_retrieval_error,
(void *)expected_user_data);
(void *)expected_user_data, &call_list);
gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
static void corrupt_jwt_sig(char *jwt) {
@ -495,6 +512,7 @@ static void on_verification_bad_signature(void *user_data,
}
static void test_jwt_verifier_bad_signature(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_url_issuer);
@ -510,15 +528,17 @@ static void test_jwt_verifier_bad_signature(void) {
GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
on_verification_bad_signature,
(void *)expected_user_data);
(void *)expected_user_data, &call_list);
gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
static int httpcli_get_should_not_be_called(
const grpc_httpcli_request *request, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
grpc_httpcli_response_cb on_response, void *user_data,
grpc_call_list *call_list) {
GPR_ASSERT(0);
return 1;
}
@ -532,14 +552,16 @@ static void on_verification_bad_format(void *user_data,
}
static void test_jwt_verifier_bad_format(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
grpc_jwt_verifier_verify(verifier, NULL, "bad jwt", expected_audience,
on_verification_bad_format,
(void *)expected_user_data);
(void *)expected_user_data, &call_list);
grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
}
/* find verification key: bad jks, cannot find key in jks */

@ -93,7 +93,7 @@ char *grpc_test_fetch_oauth2_token_with_credentials(grpc_credentials *creds) {
while (!request.is_done) {
grpc_pollset_worker worker;
grpc_pollset_work(&request.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
gpr_inf_future(GPR_CLOCK_MONOTONIC));
gpr_inf_future(GPR_CLOCK_MONOTONIC), &call_list);
}
gpr_mu_unlock(GRPC_POLLSET_MU(&request.pollset));

@ -46,18 +46,18 @@
#include "src/core/tsi/fake_transport_security.h"
static grpc_pollset g_pollset;
static grpc_workqueue *g_workqueue;
static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair(
size_t slice_size, gpr_slice *leftover_slices, size_t leftover_nslices) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
tsi_frame_protector *fake_read_protector = tsi_create_fake_protector(NULL);
tsi_frame_protector *fake_write_protector = tsi_create_fake_protector(NULL);
grpc_endpoint_test_fixture f;
grpc_endpoint_pair tcp;
tcp = grpc_iomgr_create_endpoint_pair("fixture", slice_size, g_workqueue);
grpc_endpoint_add_to_pollset(tcp.client, &g_pollset);
grpc_endpoint_add_to_pollset(tcp.server, &g_pollset);
tcp = grpc_iomgr_create_endpoint_pair("fixture", slice_size);
grpc_endpoint_add_to_pollset(tcp.client, &g_pollset, &call_list);
grpc_endpoint_add_to_pollset(tcp.server, &g_pollset, &call_list);
if (leftover_nslices == 0) {
f.client_ep =
@ -110,6 +110,7 @@ static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair(
f.server_ep =
grpc_secure_endpoint_create(fake_write_protector, tcp.server, NULL, 0);
grpc_call_list_run(&call_list);
return f;
}
@ -137,41 +138,56 @@ static grpc_endpoint_test_config configs[] = {
secure_endpoint_create_fixture_tcp_socketpair_leftover, clean_up},
};
static void inc_call_ctr(void *arg, int success, grpc_call_list *call_list) {
++*(int *)arg;
;
}
static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) {
grpc_endpoint_test_fixture f = config.create_fixture(slice_size);
gpr_slice_buffer incoming;
gpr_slice s =
gpr_slice_from_copied_string("hello world 12345678900987654321");
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
int n = 0;
grpc_closure done_closure;
gpr_log(GPR_INFO, "Start test left over");
gpr_slice_buffer_init(&incoming);
GPR_ASSERT(grpc_endpoint_read(f.client_ep, &incoming, NULL) ==
GRPC_ENDPOINT_DONE);
grpc_closure_init(&done_closure, inc_call_ctr, &n);
grpc_endpoint_read(f.client_ep, &incoming, NULL, &call_list);
grpc_call_list_run(&call_list);
GPR_ASSERT(n == 1);
GPR_ASSERT(incoming.count == 1);
GPR_ASSERT(0 == gpr_slice_cmp(s, incoming.slices[0]));
grpc_endpoint_shutdown(f.client_ep);
grpc_endpoint_shutdown(f.server_ep);
grpc_endpoint_destroy(f.client_ep);
grpc_endpoint_destroy(f.server_ep);
grpc_endpoint_shutdown(f.client_ep, &call_list);
grpc_endpoint_shutdown(f.server_ep, &call_list);
grpc_endpoint_destroy(f.client_ep, &call_list);
grpc_endpoint_destroy(f.server_ep, &call_list);
grpc_call_list_run(&call_list);
gpr_slice_unref(s);
gpr_slice_buffer_destroy(&incoming);
clean_up();
}
static void destroy_pollset(void *p) { grpc_pollset_destroy(p); }
static void destroy_pollset(void *p, int success, grpc_call_list *call_list) {
grpc_pollset_destroy(p);
}
int main(int argc, char **argv) {
grpc_closure destroyed;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_test_init(argc, argv);
grpc_init();
g_workqueue = grpc_workqueue_create();
grpc_pollset_init(&g_pollset);
grpc_endpoint_tests(configs[0], &g_pollset);
test_leftover(configs[1], 1);
GRPC_WORKQUEUE_UNREF(g_workqueue, "destroy");
grpc_pollset_shutdown(&g_pollset, destroy_pollset, &g_pollset);
grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
grpc_pollset_shutdown(&g_pollset, &destroyed, &call_list);
grpc_call_list_run(&call_list);
grpc_shutdown();
return 0;

@ -75,12 +75,14 @@ static void test_wait_empty(void) {
shutdown_and_destroy(cc);
}
static void do_nothing_end_completion(void *arg, grpc_cq_completion *c) {}
static void do_nothing_end_completion(void *arg, grpc_cq_completion *c,
grpc_call_list *call_list) {}
static void test_cq_end_op(void) {
grpc_event ev;
grpc_completion_queue *cc;
grpc_cq_completion completion;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
void *tag = create_test_tag();
LOG_TEST("test_cq_end_op");
@ -88,7 +90,8 @@ static void test_cq_end_op(void) {
cc = grpc_completion_queue_create(NULL);
grpc_cq_begin_op(cc);
grpc_cq_end_op(cc, tag, 1, do_nothing_end_completion, NULL, &completion);
grpc_cq_end_op(cc, tag, 1, do_nothing_end_completion, NULL, &completion,
&call_list);
ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
@ -96,6 +99,7 @@ static void test_cq_end_op(void) {
GPR_ASSERT(ev.success);
shutdown_and_destroy(cc);
GPR_ASSERT(grpc_call_list_empty(call_list));
}
static void test_shutdown_then_next_polling(void) {
@ -129,6 +133,7 @@ static void test_pluck(void) {
grpc_completion_queue *cc;
void *tags[128];
grpc_cq_completion completions[GPR_ARRAY_SIZE(tags)];
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
unsigned i, j;
LOG_TEST("test_pluck");
@ -145,7 +150,7 @@ static void test_pluck(void) {
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
grpc_cq_begin_op(cc);
grpc_cq_end_op(cc, tags[i], 1, do_nothing_end_completion, NULL,
&completions[i]);
&completions[i], &call_list);
}
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
@ -157,7 +162,7 @@ static void test_pluck(void) {
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
grpc_cq_begin_op(cc);
grpc_cq_end_op(cc, tags[i], 1, do_nothing_end_completion, NULL,
&completions[i]);
&completions[i], &call_list);
}
for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) {
@ -167,6 +172,7 @@ static void test_pluck(void) {
}
shutdown_and_destroy(cc);
GPR_ASSERT(grpc_call_list_empty(call_list));
}
#define TEST_THREAD_EVENTS 10000
@ -186,13 +192,15 @@ gpr_timespec ten_seconds_time(void) {
return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
}
static void free_completion(void *arg, grpc_cq_completion *completion) {
static void free_completion(void *arg, grpc_cq_completion *completion,
grpc_call_list *call_list) {
gpr_free(completion);
}
static void producer_thread(void *arg) {
test_thread_options *opt = arg;
int i;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_log(GPR_INFO, "producer %d started", opt->id);
gpr_event_set(&opt->on_started, (void *)(gpr_intptr)1);
@ -210,12 +218,13 @@ static void producer_thread(void *arg) {
gpr_log(GPR_INFO, "producer %d phase 2", opt->id);
for (i = 0; i < TEST_THREAD_EVENTS; i++) {
grpc_cq_end_op(opt->cc, (void *)(gpr_intptr)1, 1, free_completion, NULL,
gpr_malloc(sizeof(grpc_cq_completion)));
gpr_malloc(sizeof(grpc_cq_completion)), &call_list);
opt->events_triggered++;
}
gpr_log(GPR_INFO, "producer %d phase 2 done", opt->id);
gpr_event_set(&opt->on_finished, (void *)(gpr_intptr)1);
GPR_ASSERT(grpc_call_list_empty(call_list));
}
static void consumer_thread(void *arg) {

@ -116,7 +116,7 @@ static void free_port_using_server(char *server, int port) {
while (!pr.done) {
grpc_pollset_worker worker;
grpc_pollset_work(&pr.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), &call_list);
}
gpr_mu_unlock(GRPC_POLLSET_MU(&pr.pollset));
@ -272,7 +272,7 @@ static int pick_port_using_server(char *server) {
while (pr.port == -1) {
grpc_pollset_worker worker;
grpc_pollset_work(&pr.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), &call_list);
}
gpr_mu_unlock(GRPC_POLLSET_MU(&pr.pollset));

@ -138,10 +138,12 @@ void reconnect_server_poll(reconnect_server *server, int seconds) {
gpr_timespec deadline =
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(seconds, GPR_TIMESPAN));
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_mu_lock(GRPC_POLLSET_MU(&server->pollset));
grpc_pollset_work(&server->pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
deadline);
deadline, &call_list);
gpr_mu_unlock(GRPC_POLLSET_MU(&server->pollset));
grpc_call_list_run(&call_list);
}
void reconnect_server_clear_timestamps(reconnect_server *server) {

Loading…
Cancel
Save