From dfff1b8126a1f83833fd99626517f28d1e68453a Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 21 Sep 2015 14:39:57 -0700 Subject: [PATCH] Call list progress --- src/core/census/grpc_filter.c | 6 +- src/core/channel/channel_stack.c | 5 +- src/core/channel/channel_stack.h | 6 +- src/core/channel/client_channel.c | 9 +- src/core/channel/compress_filter.c | 3 +- src/core/channel/connected_channel.c | 19 +- src/core/channel/http_client_filter.c | 3 +- src/core/channel/http_server_filter.c | 3 +- src/core/channel/noop_filter.c | 3 +- .../client_config/lb_policies/pick_first.c | 2 +- .../client_config/resolvers/dns_resolver.c | 2 +- .../resolvers/sockaddr_resolver.c | 2 +- src/core/client_config/subchannel.c | 18 +- src/core/client_config/subchannel_factory.c | 6 +- src/core/client_config/subchannel_factory.h | 5 +- .../merge_channel_args.c | 5 +- src/core/httpcli/httpcli.c | 7 +- src/core/httpcli/httpcli.h | 6 +- src/core/iomgr/alarm.c | 3 +- src/core/iomgr/pollset.h | 7 +- src/core/iomgr/pollset_posix.c | 20 +- src/core/iomgr/resolve_address.h | 1 + src/core/security/client_auth_filter.c | 3 +- .../security/google_default_credentials.c | 2 +- src/core/security/server_auth_filter.c | 3 +- src/core/security/server_secure_chttp2.c | 20 +- src/core/surface/call.c | 22 +- src/core/surface/call.h | 3 +- src/core/surface/channel.c | 19 +- src/core/surface/channel.h | 14 +- src/core/surface/channel_connectivity.c | 40 +-- src/core/surface/channel_create.c | 60 ++-- src/core/surface/completion_queue.c | 32 +- src/core/surface/completion_queue.h | 6 +- src/core/surface/lame_client.c | 40 ++- src/core/surface/secure_channel_create.c | 14 +- src/core/surface/server.c | 288 ++++++++++-------- src/core/surface/server.h | 9 +- src/core/surface/server_chttp2.c | 36 ++- src/core/transport/chttp2/frame_data.c | 3 +- src/core/transport/chttp2/frame_data.h | 4 +- src/core/transport/chttp2/frame_goaway.c | 3 +- src/core/transport/chttp2/frame_goaway.h | 4 +- src/core/transport/chttp2/frame_ping.c | 7 +- src/core/transport/chttp2/frame_ping.h | 4 +- src/core/transport/chttp2/frame_rst_stream.c | 3 +- src/core/transport/chttp2/frame_rst_stream.h | 4 +- src/core/transport/chttp2/frame_settings.c | 3 +- src/core/transport/chttp2/frame_settings.h | 4 +- .../transport/chttp2/frame_window_update.c | 3 +- .../transport/chttp2/frame_window_update.h | 4 +- src/core/transport/chttp2/hpack_parser.c | 3 +- src/core/transport/chttp2/hpack_parser.h | 4 +- src/core/transport/chttp2/internal.h | 21 +- src/core/transport/chttp2/parsing.c | 30 +- src/core/transport/chttp2/writing.c | 22 +- src/core/transport/chttp2_transport.c | 284 ++++++++--------- src/core/transport/chttp2_transport.h | 5 +- src/core/transport/connectivity_state.c | 5 +- src/core/transport/connectivity_state.h | 3 +- src/core/transport/transport.c | 52 ++-- src/core/transport/transport.h | 22 +- src/core/transport/transport_impl.h | 16 +- test/core/bad_client/bad_client.c | 14 +- test/core/channel/channel_stack_test.c | 32 +- .../core/end2end/fixtures/h2_sockpair+trace.c | 33 +- test/core/end2end/fixtures/h2_sockpair.c | 33 +- .../core/end2end/fixtures/h2_sockpair_1byte.c | 33 +- test/core/httpcli/httpcli_test.c | 29 +- test/core/iomgr/alarm_list_test.c | 63 ++-- test/core/iomgr/alarm_test.c | 10 +- test/core/iomgr/endpoint_pair_test.c | 22 +- test/core/iomgr/endpoint_tests.c | 3 +- test/core/iomgr/fd_conservation_posix_test.c | 11 +- test/core/iomgr/fd_posix_test.c | 121 +++++--- test/core/iomgr/resolve_address_test.c | 6 +- test/core/iomgr/tcp_client_posix_test.c | 69 +++-- test/core/security/credentials_test.c | 118 ++++--- test/core/security/jwt_verifier_test.c | 60 ++-- test/core/security/oauth2_utils.c | 2 +- test/core/security/secure_endpoint_test.c | 44 ++- test/core/surface/completion_queue_test.c | 21 +- test/core/util/port_posix.c | 4 +- test/core/util/reconnect_server.c | 4 +- 84 files changed, 1187 insertions(+), 810 deletions(-) diff --git a/src/core/census/grpc_filter.c b/src/core/census/grpc_filter.c index d66f29228b0..fa318c4e541 100644 --- a/src/core/census/grpc_filter.c +++ b/src/core/census/grpc_filter.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); diff --git a/src/core/channel/channel_stack.c b/src/core/channel/channel_stack.c index c767a87b208..10fbd520c32 100644 --- a/src/core/channel/channel_stack.c +++ b/src/core/channel/channel_stack.c @@ -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); } diff --git a/src/core/channel/channel_stack.h b/src/core/channel/channel_stack.h index 190247b3f10..5afe7f258a0 100644 --- a/src/core/channel/channel_stack.h +++ b/src/core/channel/channel_stack.h @@ -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); diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c index 6618336e938..62f81daf447 100644 --- a/src/core/channel/client_channel.c +++ b/src/core/channel/client_channel.c @@ -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); } diff --git a/src/core/channel/compress_filter.c b/src/core/channel/compress_filter.c index 5a7403ccfdc..e2be603e266 100644 --- a/src/core/channel/compress_filter.c +++ b/src/core/channel/compress_filter.c @@ -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; diff --git a/src/core/channel/connected_channel.c b/src/core/channel/connected_channel.c index 00a4d61afed..1af5eae9478 100644 --- a/src/core/channel/connected_channel.c +++ b/src/core/channel/connected_channel.c @@ -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 = { diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c index 4e9eac72ba8..d0adafc0487 100644 --- a/src/core/channel/http_client_filter.c +++ b/src/core/channel/http_client_filter.c @@ -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; diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c index 201adf4f35c..70cc4f298ac 100644 --- a/src/core/channel/http_server_filter.c +++ b/src/core/channel/http_server_filter.c @@ -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 */ diff --git a/src/core/channel/noop_filter.c b/src/core/channel/noop_filter.c index d4f1acb4c5c..de75f836541 100644 --- a/src/core/channel/noop_filter.c +++ b/src/core/channel/noop_filter.c @@ -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; diff --git a/src/core/client_config/lb_policies/pick_first.c b/src/core/client_config/lb_policies/pick_first.c index 6dc52f43ce7..8ea774bebcd 100644 --- a/src/core/client_config/lb_policies/pick_first.c +++ b/src/core/client_config/lb_policies/pick_first.c @@ -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); diff --git a/src/core/client_config/resolvers/dns_resolver.c b/src/core/client_config/resolvers/dns_resolver.c index 5750db4b434..0fc89ed864b 100644 --- a/src/core/client_config/resolvers/dns_resolver.c +++ b/src/core/client_config/resolvers/dns_resolver.c @@ -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); diff --git a/src/core/client_config/resolvers/sockaddr_resolver.c b/src/core/client_config/resolvers/sockaddr_resolver.c index 38293b0f133..2729036d4f3 100644 --- a/src/core/client_config/resolvers/sockaddr_resolver.c +++ b/src/core/client_config/resolvers/sockaddr_resolver.c @@ -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); diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c index bae705f9c39..48df4bbd31c 100644 --- a/src/core/client_config/subchannel.c +++ b/src/core/client_config/subchannel.c @@ -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; } diff --git a/src/core/client_config/subchannel_factory.c b/src/core/client_config/subchannel_factory.c index 2a569aba13f..e2526650000 100644 --- a/src/core/client_config/subchannel_factory.c +++ b/src/core/client_config/subchannel_factory.c @@ -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( diff --git a/src/core/client_config/subchannel_factory.h b/src/core/client_config/subchannel_factory.h index b588580edb7..2ff9d3c4027 100644 --- a/src/core/client_config/subchannel_factory.h +++ b/src/core/client_config/subchannel_factory.h @@ -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( diff --git a/src/core/client_config/subchannel_factory_decorators/merge_channel_args.c b/src/core/client_config/subchannel_factory_decorators/merge_channel_args.c index b2c9797b1a3..00dff6343c1 100644 --- a/src/core/client_config/subchannel_factory_decorators/merge_channel_args.c +++ b/src/core/client_config/subchannel_factory_decorators/merge_channel_args.c @@ -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); } diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c index 40ea2e9688c..fc45eda2de6 100644 --- a/src/core/httpcli/httpcli.c +++ b/src/core/httpcli/httpcli.c @@ -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); diff --git a/src/core/httpcli/httpcli.h b/src/core/httpcli/httpcli.h index 74bb1230420..6d19da37fbe 100644 --- a/src/core/httpcli/httpcli.h +++ b/src/core/httpcli/httpcli.h @@ -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); diff --git a/src/core/iomgr/alarm.c b/src/core/iomgr/alarm.c index 6e0d516f0c7..146bda477d7 100644 --- a/src/core/iomgr/alarm.c +++ b/src/core/iomgr/alarm.c @@ -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, diff --git a/src/core/iomgr/pollset.h b/src/core/iomgr/pollset.h index 98653412bb1..95ba694ff6b 100644 --- a/src/core/iomgr/pollset.h +++ b/src/core/iomgr/pollset.h @@ -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. diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 885cb29234f..10407161799 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -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. diff --git a/src/core/iomgr/resolve_address.h b/src/core/iomgr/resolve_address.h index ec8d83fffaa..72b9c1cc87e 100644 --- a/src/core/iomgr/resolve_address.h +++ b/src/core/iomgr/resolve_address.h @@ -34,6 +34,7 @@ #ifndef GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H #define GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H +#include #include "src/core/iomgr/iomgr.h" #define GRPC_MAX_SOCKADDR_SIZE 128 diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c index 0a2de4f7bb4..1d06df8533f 100644 --- a/src/core/security/client_auth_filter.c +++ b/src/core/security/client_auth_filter.c @@ -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; diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c index 5da29f5ad5d..8c3d85cc58e 100644 --- a/src/core/security/google_default_credentials.c +++ b/src/core/security/google_default_credentials.c @@ -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)); diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c index 2376cbbeb30..201288bbdd4 100644 --- a/src/core/security/server_auth_filter.c +++ b/src/core/security/server_auth_filter.c @@ -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; diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c index e6e2eee658f..0662839105d 100644 --- a/src/core/security/server_secure_chttp2.c +++ b/src/core/security/server_secure_chttp2.c @@ -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; diff --git a/src/core/surface/call.c b/src/core/surface/call.c index f2f8f0a6edc..bbaf65759dc 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -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; } diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 7a7178bc7b8..144aa7cef2c 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -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, diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index fdba09fcce2..46bea139361 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -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) { diff --git a/src/core/surface/channel.h b/src/core/surface/channel.h index 664ecc1c5ac..3f51164fcc4 100644 --- a/src/core/surface/channel.h +++ b/src/core/surface/channel.h @@ -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 */ diff --git a/src/core/surface/channel_connectivity.c b/src/core/surface/channel_connectivity.c index 4d0cf1ed8bf..7891669e353 100644 --- a/src/core/surface/channel_connectivity.c +++ b/src/core/surface/channel_connectivity.c @@ -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); } diff --git a/src/core/surface/channel_create.c b/src/core/surface/channel_create.c index f6f42b3d7ab..7ac76da10a7 100644 --- a/src/core/surface/channel_create.c +++ b/src/core/surface/channel_create.c @@ -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; } diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index b58115a93f8..49dfc3c0e1c 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -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) { diff --git a/src/core/surface/completion_queue.h b/src/core/surface/completion_queue.h index 793baff03a7..6d8d1ce9593 100644 --- a/src/core/surface/completion_queue.h +++ b/src/core/surface/completion_queue.h @@ -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); diff --git a/src/core/surface/lame_client.c b/src/core/surface/lame_client.c index a5de900effe..c5cf33f1f9c 100644 --- a/src/core/surface/lame_client.c +++ b/src/core/surface/lame_client.c @@ -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; } diff --git a/src/core/surface/secure_channel_create.c b/src/core/surface/secure_channel_create.c index 4a75d03f0a7..b5b9ee173ee 100644 --- a/src/core/surface/secure_channel_create.c +++ b/src/core/surface/secure_channel_create.c @@ -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); diff --git a/src/core/surface/server.c b/src/core/surface/server.c index e38c6028d91..24545c67e12 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -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); } diff --git a/src/core/surface/server.h b/src/core/surface/server.h index f87296797ce..2f2c5b8948d 100644 --- a/src/core/surface/server.h +++ b/src/core/surface/server.h @@ -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); diff --git a/src/core/surface/server_chttp2.c b/src/core/surface/server_chttp2.c index 91cf6ece9cd..df63d99dead 100644 --- a/src/core/surface/server_chttp2.c +++ b/src/core/surface/server_chttp2.c @@ -43,15 +43,17 @@ #include 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; } diff --git a/src/core/transport/chttp2/frame_data.c b/src/core/transport/chttp2/frame_data.c index 403358016d3..ef12c910cd7 100644 --- a/src/core/transport/chttp2/frame_data.c +++ b/src/core/transport/chttp2/frame_data.c @@ -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; diff --git a/src/core/transport/chttp2/frame_data.h b/src/core/transport/chttp2/frame_data.h index 23957b05ada..7530f0f6446 100644 --- a/src/core/transport/chttp2/frame_data.h +++ b/src/core/transport/chttp2/frame_data.h @@ -36,6 +36,7 @@ /* Parser for GRPC streams embedded in DATA frames */ +#include "src/core/iomgr/iomgr.h" #include #include #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); diff --git a/src/core/transport/chttp2/frame_goaway.c b/src/core/transport/chttp2/frame_goaway.c index 09d4da234c5..1c2bce6736d 100644 --- a/src/core/transport/chttp2/frame_goaway.c +++ b/src/core/transport/chttp2/frame_goaway.c @@ -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; diff --git a/src/core/transport/chttp2/frame_goaway.h b/src/core/transport/chttp2/frame_goaway.h index 9c5edfc8215..ec991f43503 100644 --- a/src/core/transport/chttp2/frame_goaway.h +++ b/src/core/transport/chttp2/frame_goaway.h @@ -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 #include @@ -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, diff --git a/src/core/transport/chttp2/frame_ping.c b/src/core/transport/chttp2/frame_ping.c index 10d1e0a523c..2fb8850a459 100644 --- a/src/core/transport/chttp2/frame_ping.c +++ b/src/core/transport/chttp2/frame_ping.c @@ -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; diff --git a/src/core/transport/chttp2/frame_ping.h b/src/core/transport/chttp2/frame_ping.h index 99197e8352f..70e19eb8ab7 100644 --- a/src/core/transport/chttp2/frame_ping.h +++ b/src/core/transport/chttp2/frame_ping.h @@ -35,6 +35,7 @@ #define GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_PING_H #include +#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 */ diff --git a/src/core/transport/chttp2/frame_rst_stream.c b/src/core/transport/chttp2/frame_rst_stream.c index 67da245239c..7cf8abe88f7 100644 --- a/src/core/transport/chttp2/frame_rst_stream.c +++ b/src/core/transport/chttp2/frame_rst_stream.c @@ -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; diff --git a/src/core/transport/chttp2/frame_rst_stream.h b/src/core/transport/chttp2/frame_rst_stream.h index ed69e588af3..17d57fae5e2 100644 --- a/src/core/transport/chttp2/frame_rst_stream.h +++ b/src/core/transport/chttp2/frame_rst_stream.h @@ -36,6 +36,7 @@ #include #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 */ diff --git a/src/core/transport/chttp2/frame_settings.c b/src/core/transport/chttp2/frame_settings.c index 54d3694a5c3..78bd4bb09dd 100644 --- a/src/core/transport/chttp2/frame_settings.c +++ b/src/core/transport/chttp2/frame_settings.c @@ -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); diff --git a/src/core/transport/chttp2/frame_settings.h b/src/core/transport/chttp2/frame_settings.h index 0ac68a9fa85..a04a28b7da8 100644 --- a/src/core/transport/chttp2/frame_settings.h +++ b/src/core/transport/chttp2/frame_settings.h @@ -37,6 +37,7 @@ #include #include #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 */ diff --git a/src/core/transport/chttp2/frame_window_update.c b/src/core/transport/chttp2/frame_window_update.c index ea13969e8cc..51eb2613469 100644 --- a/src/core/transport/chttp2/frame_window_update.c +++ b/src/core/transport/chttp2/frame_window_update.c @@ -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; diff --git a/src/core/transport/chttp2/frame_window_update.h b/src/core/transport/chttp2/frame_window_update.h index deba801d002..7f1168e551d 100644 --- a/src/core/transport/chttp2/frame_window_update.h +++ b/src/core/transport/chttp2/frame_window_update.h @@ -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 #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 */ diff --git a/src/core/transport/chttp2/hpack_parser.c b/src/core/transport/chttp2/hpack_parser.c index 9c40e8a4e60..e3b8e54e8d4 100644 --- a/src/core/transport/chttp2/hpack_parser.c +++ b/src/core/transport/chttp2/hpack_parser.c @@ -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))) { diff --git a/src/core/transport/chttp2/hpack_parser.h b/src/core/transport/chttp2/hpack_parser.h index 4f489d67fb4..c9ae6a97675 100644 --- a/src/core/transport/chttp2/hpack_parser.h +++ b/src/core/transport/chttp2/hpack_parser.h @@ -37,6 +37,7 @@ #include #include +#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 */ diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h index 386f2dd3156..b9dbbc25eef 100644 --- a/src/core/transport/chttp2/internal.h +++ b/src/core/transport/chttp2/internal.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); diff --git a/src/core/transport/chttp2/parsing.c b/src/core/transport/chttp2/parsing.c index f26f4467872..2d95963f1fd 100644 --- a/src/core/transport/chttp2/parsing.c +++ b/src/core/transport/chttp2/parsing.c @@ -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, diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c index db6715b43a5..18f4bfbc77c 100644 --- a/src/core/transport/chttp2/writing.c +++ b/src/core/transport/chttp2/writing.c @@ -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; diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index bc056ac0b88..acd7cbdc1d7 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -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); } diff --git a/src/core/transport/chttp2_transport.h b/src/core/transport/chttp2_transport.h index fa0d6e4151e..e963e16707b 100644 --- a/src/core/transport/chttp2_transport.h +++ b/src/core/transport/chttp2_transport.h @@ -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 */ diff --git a/src/core/transport/connectivity_state.c b/src/core/transport/connectivity_state.c index 8b2e1b9b02c..dc8392159b2 100644 --- a/src/core/transport/connectivity_state.c +++ b/src/core/transport/connectivity_state.c @@ -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); diff --git a/src/core/transport/connectivity_state.h b/src/core/transport/connectivity_state.h index a29c655b4e8..3f92b22d5d0 100644 --- a/src/core/transport/connectivity_state.h +++ b/src/core/transport/connectivity_state.h @@ -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 */ diff --git a/src/core/transport/transport.c b/src/core/transport/transport.c index 3f6b93c3e8c..f7c87c1e90b 100644 --- a/src/core/transport/transport.c +++ b/src/core/transport/transport.c @@ -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); } diff --git a/src/core/transport/transport.h b/src/core/transport/transport.h index 271891d430a..d5383ad11a4 100644 --- a/src/core/transport/transport.h +++ b/src/core/transport/transport.h @@ -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 */ diff --git a/src/core/transport/transport_impl.h b/src/core/transport/transport_impl.h index d3bbdf6c279..9adb16b9411 100644 --- a/src/core/transport/transport_impl.h +++ b/src/core/transport/transport_impl.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 */ diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c index e89d5b3d398..fd37fce9761 100644 --- a/test/core/bad_client/bad_client.c +++ b/test/core/bad_client/bad_client.c @@ -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); diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c index 60129afc43a..07df9212701 100644 --- a/test/core/channel/channel_stack_test.c +++ b/test/core/channel/channel_stack_test.c @@ -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) { diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.c b/test/core/end2end/fixtures/h2_sockpair+trace.c index 04dbf485227..be8132bc967 100644 --- a/test/core/end2end/fixtures/h2_sockpair+trace.c +++ b/test/core/end2end/fixtures/h2_sockpair+trace.c @@ -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) { diff --git a/test/core/end2end/fixtures/h2_sockpair.c b/test/core/end2end/fixtures/h2_sockpair.c index b661dbfd603..08f918cbad2 100644 --- a/test/core/end2end/fixtures/h2_sockpair.c +++ b/test/core/end2end/fixtures/h2_sockpair.c @@ -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) { diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.c b/test/core/end2end/fixtures/h2_sockpair_1byte.c index 6cf656bcde0..46ffaff745f 100644 --- a/test/core/end2end/fixtures/h2_sockpair_1byte.c +++ b/test/core/end2end/fixtures/h2_sockpair_1byte.c @@ -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) { diff --git a/test/core/httpcli/httpcli_test.c b/test/core/httpcli/httpcli_test.c index cf2b10c021a..bcb544e5028 100644 --- a/test/core/httpcli/httpcli_test.c +++ b/test/core/httpcli/httpcli_test.c @@ -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 = "Hello world!" "

This is a test

"; @@ -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); diff --git a/test/core/iomgr/alarm_list_test.c b/test/core/iomgr/alarm_list_test.c index 56d662e61a3..8082532434c 100644 --- a/test/core/iomgr/alarm_list_test.c +++ b/test/core/iomgr/alarm_list_test.c @@ -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]); } diff --git a/test/core/iomgr/alarm_test.c b/test/core/iomgr/alarm_test.c index eafac0dc46f..bfced834097 100644 --- a/test/core/iomgr/alarm_test.c +++ b/test/core/iomgr/alarm_test.c @@ -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); diff --git a/test/core/iomgr/endpoint_pair_test.c b/test/core/iomgr/endpoint_pair_test.c index 9fe54771bd5..491effd5ae2 100644 --- a/test/core/iomgr/endpoint_pair_test.c +++ b/test/core/iomgr/endpoint_pair_test.c @@ -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; diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c index a5079f17a53..02618dfd667 100644 --- a/test/core/iomgr/endpoint_tests.c +++ b/test/core/iomgr/endpoint_tests.c @@ -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); diff --git a/test/core/iomgr/fd_conservation_posix_test.c b/test/core/iomgr/fd_conservation_posix_test.c index 30852050ceb..a1b1171b07d 100644 --- a/test/core/iomgr/fd_conservation_posix_test.c +++ b/test/core/iomgr/fd_conservation_posix_test.c @@ -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; } diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c index ae6b56da772..f89d6c78248 100644 --- a/test/core/iomgr/fd_posix_test.c +++ b/test/core/iomgr/fd_posix_test.c @@ -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; } diff --git a/test/core/iomgr/resolve_address_test.c b/test/core/iomgr/resolve_address_test.c index 668c5399f90..2ea3b56ee62 100644 --- a/test/core/iomgr/resolve_address_test.c +++ b/test/core/iomgr/resolve_address_test.c @@ -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); } diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c index 4a6786c0a24..a5a3d0ea7ec 100644 --- a/test/core/iomgr/tcp_client_posix_test.c +++ b/test/core/iomgr/tcp_client_posix_test.c @@ -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; } diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 97ebaa05708..3d0ed094c92 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -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( diff --git a/test/core/security/jwt_verifier_test.c b/test/core/security/jwt_verifier_test.c index 5cc8b2e9be6..00a079f54e2 100644 --- a/test/core/security/jwt_verifier_test.c +++ b/test/core/security/jwt_verifier_test.c @@ -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 */ diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c index 45beb05c1c8..fad52d0c59d 100644 --- a/test/core/security/oauth2_utils.c +++ b/test/core/security/oauth2_utils.c @@ -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)); diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index e0bdea527ad..f7948b56afb 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -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; diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index 0eeb5dac459..06bab3279e6 100644 --- a/test/core/surface/completion_queue_test.c +++ b/test/core/surface/completion_queue_test.c @@ -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) { diff --git a/test/core/util/port_posix.c b/test/core/util/port_posix.c index fa3798aa3c8..98b5686e911 100644 --- a/test/core/util/port_posix.c +++ b/test/core/util/port_posix.c @@ -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)); diff --git a/test/core/util/reconnect_server.c b/test/core/util/reconnect_server.c index b4eb7ed916e..eeb3ecb55a8 100644 --- a/test/core/util/reconnect_server.c +++ b/test/core/util/reconnect_server.c @@ -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) {