Call list progress

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

@ -128,7 +128,8 @@ static void server_start_transport_op(grpc_call_element* elem,
static void client_init_call_elem(grpc_call_element* elem, static void client_init_call_elem(grpc_call_element* elem,
const void* server_transport_data, 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; call_data* d = elem->call_data;
GPR_ASSERT(d != NULL); GPR_ASSERT(d != NULL);
d->start_ts = gpr_now(GPR_CLOCK_REALTIME); 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, static void server_init_call_elem(grpc_call_element* elem,
const void* server_transport_data, 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; call_data* d = elem->call_data;
GPR_ASSERT(d != NULL); GPR_ASSERT(d != NULL);
d->start_ts = gpr_now(GPR_CLOCK_REALTIME); d->start_ts = gpr_now(GPR_CLOCK_REALTIME);

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

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

@ -459,7 +459,7 @@ static void on_lb_policy_state_changed(void *arg, int iomgr_success,
on_lb_policy_state_changed_locked(w, call_list); on_lb_policy_state_changed_locked(w, call_list);
gpr_mu_unlock(&w->chand->mu_config); 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); 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_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, 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 */ /* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem, static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data, 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; call_data *calld = elem->call_data;
/* TODO(ctiller): is there something useful we can do here? */ /* 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) { if (chand->lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel", call_list); 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); grpc_pollset_set_destroy(&chand->pollset_set);
gpr_mu_destroy(&chand->mu_config); gpr_mu_destroy(&chand->mu_config);
} }

@ -282,7 +282,8 @@ static void compress_start_transport_stream_op(grpc_call_element *elem,
/* Constructor for call_data */ /* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem, static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data, 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 */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;

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

@ -165,7 +165,8 @@ static void hc_start_transport_op(grpc_call_element *elem,
/* Constructor for call_data */ /* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem, static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data, 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; call_data *calld = elem->call_data;
calld->sent_initial_metadata = 0; calld->sent_initial_metadata = 0;
calld->got_initial_metadata = 0; calld->got_initial_metadata = 0;

@ -238,7 +238,8 @@ static void hs_start_transport_op(grpc_call_element *elem,
/* Constructor for call_data */ /* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem, static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data, 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 */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
/* initialize members */ /* initialize members */

@ -74,7 +74,8 @@ static void noop_start_transport_stream_op(grpc_call_element *elem,
/* Constructor for call_data */ /* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem, static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data, 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 */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data; channel_data *channeld = elem->channel_data;

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

@ -197,7 +197,7 @@ static void dns_destroy(grpc_resolver *gr, grpc_call_list *call_list) {
if (r->resolved_config) { if (r->resolved_config) {
grpc_client_config_unref(r->resolved_config, call_list); 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->name);
gpr_free(r->default_port); gpr_free(r->default_port);
gpr_free(r->lb_policy_name); gpr_free(r->lb_policy_name);

@ -159,7 +159,7 @@ static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r,
static void sockaddr_destroy(grpc_resolver *gr, grpc_call_list *call_list) { static void sockaddr_destroy(grpc_resolver *gr, grpc_call_list *call_list) {
sockaddr_resolver *r = (sockaddr_resolver *)gr; sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu); 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);
gpr_free(r->addrs_len); gpr_free(r->addrs_len);
gpr_free(r->lb_policy_name); gpr_free(r->lb_policy_name);

@ -143,7 +143,8 @@ struct grpc_subchannel_call {
#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1)) #define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1))
#define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)((con) + 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, static void connectivity_state_changed_locked(grpc_subchannel *c,
const char *reason, const char *reason,
grpc_call_list *call_list); 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); grpc_channel_args_destroy(c->args);
gpr_free(c->addr); gpr_free(c->addr);
grpc_mdctx_unref(c->mdctx); 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); grpc_connector_unref(c->connector, call_list);
gpr_free(c); gpr_free(c);
} }
@ -355,7 +356,7 @@ void grpc_subchannel_create_call(grpc_subchannel *c, grpc_pollset *pollset,
CONNECTION_REF_LOCKED(con, "call"); CONNECTION_REF_LOCKED(con, "call");
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
*target = create_call(con); *target = create_call(con, call_list);
notify->cb(notify->cb_arg, 1, call_list); notify->cb(notify->cb_arg, 1, call_list);
} else { } else {
waiting_for_connect *w4c = gpr_malloc(sizeof(*w4c)); 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(sw);
gpr_free(filters); gpr_free(filters);
grpc_channel_stack_destroy(stk, call_list); 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); GRPC_SUBCHANNEL_UNREF(c, "connecting", call_list);
return; 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.on_connectivity_state_change = &sw->closure;
op.bind_pollset_set = c->pollset_set; op.bind_pollset_set = c->pollset_set;
SUBCHANNEL_REF_LOCKED(c, "state_watcher"); 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")); GPR_ASSERT(!SUBCHANNEL_UNREF_LOCKED(c, "connecting"));
elem = elem =
grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(c->active), 0); 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); update_reconnect_parameters(c);
continue_connect(c, call_list); continue_connect(c, call_list);
} else { } else {
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting"); GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting", call_list);
GRPC_SUBCHANNEL_UNREF(c, "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); 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_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
grpc_subchannel_call *call = grpc_subchannel_call *call =
gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size); gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call); grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
call->connection = con; call->connection = con;
gpr_ref_init(&call->refs, 1); 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; return call;
} }

@ -36,8 +36,10 @@
void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory) { void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory) {
factory->vtable->ref(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( grpc_subchannel *grpc_subchannel_factory_create_subchannel(

@ -48,14 +48,15 @@ struct grpc_subchannel_factory {
struct grpc_subchannel_factory_vtable { struct grpc_subchannel_factory_vtable {
void (*ref)(grpc_subchannel_factory *factory); 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 *(*create_subchannel)(grpc_subchannel_factory *factory,
grpc_subchannel_args *args, grpc_subchannel_args *args,
grpc_call_list *call_list); grpc_call_list *call_list);
}; };
void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory); 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 */ /** Create a new grpc_subchannel */
grpc_subchannel *grpc_subchannel_factory_create_subchannel( grpc_subchannel *grpc_subchannel_factory_create_subchannel(

@ -47,10 +47,11 @@ static void merge_args_factory_ref(grpc_subchannel_factory *scf) {
gpr_ref(&f->refs); 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; merge_args_factory *f = (merge_args_factory *)scf;
if (gpr_unref(&f->refs)) { 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); grpc_channel_args_destroy(f->merge_args);
gpr_free(f); gpr_free(f);
} }

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

@ -147,13 +147,15 @@ void grpc_httpcli_post(grpc_httpcli_context *context, grpc_pollset *pollset,
typedef int (*grpc_httpcli_get_override)(const grpc_httpcli_request *request, typedef int (*grpc_httpcli_get_override)(const grpc_httpcli_request *request,
gpr_timespec deadline, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, 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, typedef int (*grpc_httpcli_post_override)(const grpc_httpcli_request *request,
const char *body_bytes, const char *body_bytes,
size_t body_size, size_t body_size,
gpr_timespec deadline, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, 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, void grpc_httpcli_set_override(grpc_httpcli_get_override get,
grpc_httpcli_post_override post); grpc_httpcli_post_override post);

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

@ -73,9 +73,12 @@ void grpc_pollset_destroy(grpc_pollset *pollset);
grpc_pollset_work, and it is guaranteed that GRPC_POLLSET_MU(pollset) will 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. 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, 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. /* Break one polling thread out of polling work for this pollset.
If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers. If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers.

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

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

@ -280,7 +280,8 @@ static void auth_start_transport_op(grpc_call_element *elem,
/* Constructor for call_data */ /* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem, static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data, 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; call_data *calld = elem->call_data;
calld->creds = NULL; calld->creds = NULL;
calld->host = NULL; calld->host = NULL;

@ -123,7 +123,7 @@ static int is_stack_running_on_compute_engine(void) {
while (!detector.is_done) { while (!detector.is_done) {
grpc_pollset_worker worker; grpc_pollset_worker worker;
grpc_pollset_work(&detector.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), 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)); gpr_mu_unlock(GRPC_POLLSET_MU(&detector.pollset));

@ -200,7 +200,8 @@ static void auth_start_transport_op(grpc_call_element *elem,
/* Constructor for call_data */ /* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem, static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data, 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 */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;

@ -67,6 +67,7 @@ typedef struct grpc_server_secure_state {
gpr_mu mu; gpr_mu mu;
gpr_refcount refcount; gpr_refcount refcount;
grpc_closure destroy_closure; grpc_closure destroy_closure;
grpc_closure *destroy_callback;
} grpc_server_secure_state; } grpc_server_secure_state;
static void state_ref(grpc_server_secure_state *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, 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[] = { static grpc_channel_filter const *extra_filters[] = {
&grpc_server_auth_filter, &grpc_http_server_filter}; &grpc_server_auth_filter, &grpc_http_server_filter};
grpc_server_secure_state *state = statep; 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)); GPR_ARRAY_SIZE(args_to_add));
grpc_server_setup_transport(state->server, transport, extra_filters, grpc_server_setup_transport(state->server, transport, extra_filters,
GPR_ARRAY_SIZE(extra_filters), mdctx, workqueue, GPR_ARRAY_SIZE(extra_filters), mdctx, workqueue,
args_copy); args_copy, call_list);
grpc_channel_args_destroy(args_copy); 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); workqueue = grpc_workqueue_create(call_list);
transport = grpc_create_chttp2_transport( transport = grpc_create_chttp2_transport(
grpc_server_get_channel_args(state->server), secure_endpoint, mdctx, grpc_server_get_channel_args(state->server), secure_endpoint, mdctx,
0); 0, call_list);
setup_transport(state, transport, mdctx, workqueue); setup_transport(state, transport, mdctx, workqueue, call_list);
grpc_chttp2_transport_start_reading(transport, NULL, 0); grpc_chttp2_transport_start_reading(transport, NULL, 0, call_list);
} else { } else {
/* We need to consume this here, because the server may already have gone /* We need to consume this here, because the server may already have gone
* away. */ * 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) { static void destroy_done(void *statep, int success, grpc_call_list *call_list) {
grpc_server_secure_state *state = statep; 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); gpr_mu_lock(&state->mu);
while (state->handshaking_tcp_endpoints != NULL) { while (state->handshaking_tcp_endpoints != NULL) {
grpc_endpoint_shutdown(state->handshaking_tcp_endpoints->tcp_endpoint, 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 /* Server callback: destroy the tcp listener (so we don't generate further
callbacks) */ 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_call_list *call_list) {
grpc_server_secure_state *state = statep; grpc_server_secure_state *state = statep;
grpc_tcp_server *tcp; grpc_tcp_server *tcp;
gpr_mu_lock(&state->mu); gpr_mu_lock(&state->mu);
state->is_shutdown = 1; state->is_shutdown = 1;
state->destroy_callback = callback;
tcp = state->tcp; tcp = state->tcp;
gpr_mu_unlock(&state->mu); gpr_mu_unlock(&state->mu);
grpc_closure_init(&state->destroy_closure, destroy_done, state); 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); gpr_ref_init(&state->refcount, 1);
/* Register with the server only upon success */ /* 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); grpc_call_list_run(&call_list);
return port_num; return port_num;

@ -356,7 +356,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
initial_op_ptr = &initial_op; initial_op_ptr = &initial_op;
} }
grpc_call_stack_init(channel_stack, server_transport_data, initial_op_ptr, 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) { if (parent_call != NULL) {
GRPC_CALL_INTERNAL_REF(parent_call, "child"); GRPC_CALL_INTERNAL_REF(parent_call, "child");
GPR_ASSERT(call->is_client); GPR_ASSERT(call->is_client);
@ -459,7 +459,7 @@ static void destroy_call(grpc_call *call, grpc_call_list *call_list) {
size_t i; size_t i;
grpc_call *c = call; grpc_call *c = call;
grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c), call_list); 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->mu);
gpr_mu_destroy(&c->completion_mu); gpr_mu_destroy(&c->completion_mu);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { 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) { if (completing_requests > 0) {
for (i = 0; i < completing_requests; i++) { for (i = 0; i < completing_requests; i++) {
completed_requests[i].on_complete(call, completed_requests[i].success, completed_requests[i].on_complete(call, completed_requests[i].success,
completed_requests[i].user_data); completed_requests[i].user_data,
call_list);
} }
lock(call); lock(call);
call->completing = 0; 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); *(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, 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, 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) { 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; size_t out;
const grpc_op *op; const grpc_op *op;
grpc_ioreq *req; 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_error error;
grpc_call_list call_list = GRPC_CALL_LIST_INIT; 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_cq_begin_op(call->cq);
GRPC_CALL_INTERNAL_REF(call, "completion"); GRPC_CALL_INTERNAL_REF(call, "completion");
grpc_cq_end_op(call->cq, tag, 1, done_completion, call, grpc_cq_end_op(call->cq, tag, 1, done_completion, call,
allocate_completion(call)); allocate_completion(call), &call_list);
error = GRPC_CALL_OK; error = GRPC_CALL_OK;
goto done; goto done;
} }

@ -87,7 +87,8 @@ typedef struct {
} grpc_ioreq; } grpc_ioreq;
typedef void (*grpc_ioreq_completion_func)(grpc_call *call, int success, 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, grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call,
gpr_uint32 propagation_mask, gpr_uint32 propagation_mask,

@ -272,9 +272,9 @@ void grpc_channel_internal_ref(grpc_channel *c) {
gpr_ref(&c->refs); 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; 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++) { for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) {
GRPC_MDELEM_UNREF(channel->grpc_status_elem[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 #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, gpr_log(GPR_DEBUG, "CHANNEL: unref %p %d -> %d [%s]", channel,
channel->refs.count, channel->refs.count - 1, reason); channel->refs.count, channel->refs.count - 1, reason);
#else #else
void grpc_channel_internal_unref(grpc_channel *channel) { void grpc_channel_internal_unref(grpc_channel *channel,
grpc_call_list *call_list) {
#endif #endif
if (gpr_unref(&channel->refs)) { if (gpr_unref(&channel->refs)) {
destroy_channel(channel); destroy_channel(channel, call_list);
} }
} }
void grpc_channel_destroy(grpc_channel *channel) { void grpc_channel_destroy(grpc_channel *channel) {
grpc_transport_op op; grpc_transport_op op;
grpc_channel_element *elem; grpc_channel_element *elem;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
memset(&op, 0, sizeof(op)); memset(&op, 0, sizeof(op));
op.disconnect = 1; op.disconnect = 1;
elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); 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) { grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel) {

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

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

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

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

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

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

@ -108,8 +108,9 @@ static void on_secure_transport_setup_done(void *arg,
c->connecting_endpoint = NULL; c->connecting_endpoint = NULL;
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
c->result->transport = grpc_create_chttp2_transport( c->result->transport = grpc_create_chttp2_transport(
c->args.channel_args, secure_endpoint, c->mdctx, 1); c->args.channel_args, secure_endpoint, c->mdctx, 1, call_list);
grpc_chttp2_transport_start_reading(c->result->transport, NULL, 0); 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 = gpr_malloc(sizeof(grpc_channel_filter *) * 2);
c->result->filters[0] = &grpc_http_client_filter; c->result->filters[0] = &grpc_http_client_filter;
c->result->filters[1] = &grpc_client_auth_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); 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; subchannel_factory *f = (subchannel_factory *)scf;
if (gpr_unref(&f->refs)) { if (gpr_unref(&f->refs)) {
GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
"subchannel_factory"); "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_channel_args_destroy(f->merge_args);
grpc_mdctx_unref(f->mdctx); grpc_mdctx_unref(f->mdctx);
gpr_free(f); gpr_free(f);
@ -279,7 +281,7 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
GPR_ASSERT(n <= MAX_FILTERS); GPR_ASSERT(n <= MAX_FILTERS);
channel = grpc_channel_create_from_filters(target, filters, n, args_copy, 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 = gpr_malloc(sizeof(*f));
f->base.vtable = &subchannel_factory_vtable; 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), grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel),
resolver, &call_list); resolver, &call_list);
GRPC_RESOLVER_UNREF(resolver, "create", &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_SECURITY_CONNECTOR_UNREF(&connector->base, "channel_create");
grpc_channel_args_destroy(args_copy); grpc_channel_args_destroy(args_copy);

@ -57,9 +57,11 @@
typedef struct listener { typedef struct listener {
void *arg; void *arg;
void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets, void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
size_t pollset_count); size_t pollset_count, grpc_call_list *call_list);
void (*destroy)(grpc_server *server, void *arg); void (*destroy)(grpc_server *server, void *arg, grpc_closure *closure,
grpc_call_list *call_list);
struct listener *next; struct listener *next;
grpc_closure destroy_done;
} listener; } listener;
typedef struct call_data call_data; typedef struct call_data call_data;
@ -219,19 +221,19 @@ struct grpc_server {
/** when did we print the last shutdown progress message */ /** when did we print the last shutdown progress message */
gpr_timespec last_shutdown_message_time; gpr_timespec last_shutdown_message_time;
grpc_workqueue *workqueue;
}; };
#define SERVER_FROM_CALL_ELEM(elem) \ #define SERVER_FROM_CALL_ELEM(elem) \
(((channel_data *)(elem)->channel_data)->server) (((channel_data *)(elem)->channel_data)->server)
static void begin_call(grpc_server *server, call_data *calld, static void begin_call(grpc_server *server, call_data *calld,
requested_call *rc); requested_call *rc, grpc_call_list *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);
/* Before calling maybe_finish_shutdown, we must hold mu_global and not /* Before calling maybe_finish_shutdown, we must hold mu_global and not
hold mu_call */ 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 * channel broadcaster
@ -258,14 +260,15 @@ struct shutdown_cleanup_args {
gpr_slice slice; 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; struct shutdown_cleanup_args *a = arg;
gpr_slice_unref(a->slice); gpr_slice_unref(a->slice);
gpr_free(a); gpr_free(a);
} }
static void send_shutdown(grpc_channel *channel, int send_goaway, 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; grpc_transport_op op;
struct shutdown_cleanup_args *sc; struct shutdown_cleanup_args *sc;
grpc_channel_element *elem; grpc_channel_element *elem;
@ -281,17 +284,17 @@ static void send_shutdown(grpc_channel *channel, int send_goaway,
op.on_consumed = &sc->closure; op.on_consumed = &sc->closure;
elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); 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, static void channel_broadcaster_shutdown(channel_broadcaster *cb,
int send_goaway, int send_goaway, int force_disconnect,
int force_disconnect) { grpc_call_list *call_list) {
size_t i; size_t i;
for (i = 0; i < cb->num_channels; i++) { for (i = 0; i < cb->num_channels; i++) {
send_shutdown(cb->channels[i], send_goaway, force_disconnect); send_shutdown(cb->channels[i], send_goaway, force_disconnect, call_list);
GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast"); GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast", call_list);
} }
gpr_free(cb->channels); gpr_free(cb->channels);
} }
@ -311,12 +314,12 @@ static void request_matcher_destroy(request_matcher *request_matcher) {
gpr_stack_lockfree_destroy(request_matcher->requests); 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)); grpc_call_destroy(grpc_call_from_top_element(elem));
} }
static void request_matcher_zombify_all_pending_calls( 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) { while (request_matcher->pending_head) {
call_data *calld = request_matcher->pending_head; call_data *calld = request_matcher->pending_head;
request_matcher->pending_head = calld->pending_next; request_matcher->pending_head = calld->pending_next;
@ -326,15 +329,16 @@ static void request_matcher_zombify_all_pending_calls(
grpc_closure_init( grpc_closure_init(
&calld->kill_zombie_closure, kill_zombie, &calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); 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, static void request_matcher_kill_requests(grpc_server *server,
request_matcher *rm) { request_matcher *rm,
grpc_call_list *call_list) {
int request_id; int request_id;
while ((request_id = gpr_stack_lockfree_pop(rm->requests)) != -1) { 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); 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; registered_method *rm;
size_t i; size_t i;
grpc_channel_args_destroy(server->channel_args); 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); request_matcher_destroy(&server->unregistered_request_matcher);
gpr_stack_lockfree_destroy(server->request_freelist); gpr_stack_lockfree_destroy(server->request_freelist);
GRPC_WORKQUEUE_UNREF(server->workqueue, "destroy");
gpr_free(server->cqs); gpr_free(server->cqs);
gpr_free(server->pollsets); gpr_free(server->pollsets);
gpr_free(server->shutdown_tags); gpr_free(server->shutdown_tags);
@ -373,9 +376,9 @@ static void server_delete(grpc_server *server) {
gpr_free(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)) { 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; 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; channel_data *chand = cd;
grpc_server *server = chand->server; grpc_server *server = chand->server;
gpr_log(GPR_DEBUG, "finish_destroy_channel: %p", chand->channel); gpr_log(GPR_DEBUG, "finish_destroy_channel: %p", chand->channel);
GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server"); GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server", call_list);
server_unref(server); 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; if (is_channel_orphaned(chand)) return;
GPR_ASSERT(chand->server != NULL); GPR_ASSERT(chand->server != NULL);
orphan_channel(chand); orphan_channel(chand);
server_ref(chand->server); 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 = finish_destroy_channel;
chand->finish_destroy_channel_closure.cb_arg = chand; chand->finish_destroy_channel_closure.cb_arg = chand;
gpr_log(GPR_DEBUG, "queue finish_destroy_channel: %p on %p", chand->channel, grpc_call_list_add(call_list, &chand->finish_destroy_channel_closure, 1);
chand->server->workqueue);
grpc_workqueue_push(chand->server->workqueue,
&chand->finish_destroy_channel_closure, 1);
} }
static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem, 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; call_data *calld = elem->call_data;
int request_id; int request_id;
@ -421,7 +423,7 @@ static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
calld->state = ZOMBIED; calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state); gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem); 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; return;
} }
@ -443,11 +445,11 @@ static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
gpr_mu_lock(&calld->mu_state); gpr_mu_lock(&calld->mu_state);
calld->state = ACTIVATED; calld->state = ACTIVATED;
gpr_mu_unlock(&calld->mu_state); 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; channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_server *server = chand->server; 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->host != calld->host) continue;
if (rm->method != calld->path) continue; if (rm->method != calld->path) continue;
finish_start_new_rpc(server, elem, finish_start_new_rpc(server, elem,
&rm->server_registered_method->request_matcher); &rm->server_registered_method->request_matcher,
call_list);
return; return;
} }
/* check for a wildcard method definition (no host set) */ /* 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->host != NULL) continue;
if (rm->method != calld->path) continue; if (rm->method != calld->path) continue;
finish_start_new_rpc(server, elem, finish_start_new_rpc(server, elem,
&rm->server_registered_method->request_matcher); &rm->server_registered_method->request_matcher,
call_list);
return; 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) { static int num_listeners(grpc_server *server) {
@ -494,8 +499,9 @@ static int num_listeners(grpc_server *server) {
return n; return n;
} }
static void done_shutdown_event(void *server, grpc_cq_completion *completion) { static void done_shutdown_event(void *server, grpc_cq_completion *completion,
server_unref(server); grpc_call_list *call_list) {
server_unref(server, call_list);
} }
static int num_channels(grpc_server *server) { static int num_channels(grpc_server *server) {
@ -508,25 +514,27 @@ static int num_channels(grpc_server *server) {
return n; 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; 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( 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) { for (rm = server->registered_methods; rm; rm = rm->next) {
request_matcher_kill_requests(server, &rm->request_matcher); request_matcher_kill_requests(server, &rm->request_matcher, call_list);
request_matcher_zombify_all_pending_calls(&rm->request_matcher, request_matcher_zombify_all_pending_calls(&rm->request_matcher, call_list);
server->workqueue);
} }
} }
static void maybe_finish_shutdown(grpc_server *server) { static void maybe_finish_shutdown(grpc_server *server,
grpc_call_list *call_list) {
size_t i; size_t i;
if (!gpr_atm_acq_load(&server->shutdown_flag) || server->shutdown_published) { if (!gpr_atm_acq_load(&server->shutdown_flag) || server->shutdown_published) {
return; return;
} }
kill_pending_work_locked(server); kill_pending_work_locked(server, call_list);
if (server->root_channel_data.next != &server->root_channel_data || if (server->root_channel_data.next != &server->root_channel_data ||
server->listeners_destroyed < num_listeners(server)) { server->listeners_destroyed < num_listeners(server)) {
@ -548,7 +556,7 @@ static void maybe_finish_shutdown(grpc_server *server) {
server_ref(server); server_ref(server);
grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, 1, grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, 1,
done_shutdown_event, server, 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; 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; grpc_call_element *elem = ptr;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
gpr_timespec op_deadline; gpr_timespec op_deadline;
if (success && !calld->got_initial_metadata) { if (success && !calld->got_initial_metadata) {
@ -587,7 +594,7 @@ static void server_on_recv(void *ptr, int success) {
} }
if (calld->host && calld->path) { if (calld->host && calld->path) {
calld->got_initial_metadata = 1; calld->got_initial_metadata = 1;
start_new_rpc(elem); start_new_rpc(elem, call_list);
} }
break; break;
} }
@ -604,8 +611,7 @@ static void server_on_recv(void *ptr, int success) {
calld->state = ZOMBIED; calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state); gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem); grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_workqueue_push(chand->server->workqueue, grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
&calld->kill_zombie_closure, 1);
} else { } else {
gpr_mu_unlock(&calld->mu_state); gpr_mu_unlock(&calld->mu_state);
} }
@ -616,8 +622,7 @@ static void server_on_recv(void *ptr, int success) {
calld->state = ZOMBIED; calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state); gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem); grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_workqueue_push(chand->server->workqueue, grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
&calld->kill_zombie_closure, 1);
} else if (calld->state == PENDING) { } else if (calld->state == PENDING) {
calld->state = ZOMBIED; calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state); gpr_mu_unlock(&calld->mu_state);
@ -629,7 +634,7 @@ static void server_on_recv(void *ptr, int success) {
break; 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, 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, 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); GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
server_mutate_op(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, 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)); 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; channel_data *chand = cd;
grpc_server *server = chand->server; grpc_server *server = chand->server;
if (chand->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) { 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; op.connectivity_state = &chand->connectivity_state;
grpc_channel_next_op(grpc_channel_stack_element( grpc_channel_next_op(grpc_channel_stack_element(
grpc_channel_get_channel_stack(chand->channel), 0), grpc_channel_get_channel_stack(chand->channel), 0),
&op); &op, call_list);
} else { } else {
gpr_mu_lock(&server->mu_global); gpr_mu_lock(&server->mu_global);
destroy_channel(chand); destroy_channel(chand, call_list);
gpr_mu_unlock(&server->mu_global); 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, static void init_call_elem(grpc_call_element *elem,
const void *server_transport_data, 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; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
memset(calld, 0, sizeof(call_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); 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; channel_data *chand = elem->channel_data;
call_data *calld = elem->call_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); 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, static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, const grpc_channel_args *args,
grpc_mdctx *metadata_context, int is_first, grpc_mdctx *metadata_context, int is_first,
int is_last) { int is_last, grpc_call_list *call_list) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
GPR_ASSERT(is_first); GPR_ASSERT(is_first);
GPR_ASSERT(!is_last); GPR_ASSERT(!is_last);
@ -733,7 +742,8 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
channel_connectivity_changed, chand); 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; size_t i;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
if (chand->registered_methods) { if (chand->registered_methods) {
@ -752,11 +762,11 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
chand->next->prev = chand->prev; chand->next->prev = chand->prev;
chand->prev->next = chand->next; chand->prev->next = chand->next;
chand->next = chand->prev = chand; chand->next = chand->prev = chand;
maybe_finish_shutdown(chand->server); maybe_finish_shutdown(chand->server, call_list);
gpr_mu_unlock(&chand->server->mu_global); gpr_mu_unlock(&chand->server->mu_global);
GRPC_MDSTR_UNREF(chand->path_key); GRPC_MDSTR_UNREF(chand->path_key);
GRPC_MDSTR_UNREF(chand->authority_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); gpr_ref_init(&server->internal_refcount, 1);
server->root_channel_data.next = server->root_channel_data.prev = server->root_channel_data.next = server->root_channel_data.prev =
&server->root_channel_data; &server->root_channel_data;
server->workqueue = grpc_workqueue_create();
/* TODO(ctiller): expose a channel_arg for this */ /* TODO(ctiller): expose a channel_arg for this */
server->max_requested_calls = 32768; 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) { void grpc_server_start(grpc_server *server) {
listener *l; listener *l;
size_t i; size_t i;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count); server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
for (i = 0; i < server->cq_count; i++) { for (i = 0; i < server->cq_count; i++) {
server->pollsets[i] = grpc_cq_pollset(server->cqs[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) { 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, void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
grpc_channel_filter const **extra_filters, grpc_channel_filter const **extra_filters,
size_t num_extra_filters, grpc_mdctx *mdctx, size_t num_extra_filters, grpc_mdctx *mdctx,
grpc_workqueue *workqueue, 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; size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
grpc_channel_filter const **filters = grpc_channel_filter const **filters =
gpr_malloc(sizeof(grpc_channel_filter *) * num_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++) { for (i = 0; i < s->cq_count; i++) {
memset(&op, 0, sizeof(op)); memset(&op, 0, sizeof(op));
op.bind_pollset = grpc_cq_pollset(s->cqs[i]); 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, 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( chand = (channel_data *)grpc_channel_stack_element(
grpc_channel_get_channel_stack(channel), 0) grpc_channel_get_channel_stack(channel), 0)
->channel_data; ->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.on_connectivity_state_change = &chand->channel_connectivity_changed;
op.connectivity_state = &chand->connectivity_state; op.connectivity_state = &chand->connectivity_state;
op.disconnect = gpr_atm_acq_load(&s->shutdown_flag) != 0; 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; (void) done_arg;
gpr_free(storage); 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, void grpc_server_shutdown_and_notify(grpc_server *server,
grpc_completion_queue *cq, void *tag) { grpc_completion_queue *cq, void *tag) {
listener *l; listener *l;
shutdown_tag *sdt; shutdown_tag *sdt;
channel_broadcaster broadcaster; channel_broadcaster broadcaster;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
GRPC_SERVER_LOG_SHUTDOWN(GPR_INFO, server, cq, tag); 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); grpc_cq_begin_op(cq);
if (server->shutdown_published) { if (server->shutdown_published) {
grpc_cq_end_op(cq, tag, 1, done_published_shutdown, NULL, 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); gpr_mu_unlock(&server->mu_global);
return; goto done;
} }
server->shutdown_tags = server->shutdown_tags =
gpr_realloc(server->shutdown_tags, gpr_realloc(server->shutdown_tags,
@ -1020,7 +1043,7 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
sdt->cq = cq; sdt->cq = cq;
if (gpr_atm_acq_load(&server->shutdown_flag)) { if (gpr_atm_acq_load(&server->shutdown_flag)) {
gpr_mu_unlock(&server->mu_global); gpr_mu_unlock(&server->mu_global);
return; goto done;
} }
server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME); 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 */ /* collect all unregistered then registered calls */
gpr_mu_lock(&server->mu_call); 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_mu_unlock(&server->mu_call);
gpr_atm_rel_store(&server->shutdown_flag, 1); gpr_atm_rel_store(&server->shutdown_flag, 1);
maybe_finish_shutdown(server); maybe_finish_shutdown(server, &call_list);
gpr_mu_unlock(&server->mu_global); gpr_mu_unlock(&server->mu_global);
/* Shutdown listeners */ /* Shutdown listeners */
for (l = server->listeners; l; l = l->next) { 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) { done:
grpc_server *server = s; grpc_call_list_run(&call_list);
gpr_mu_lock(&server->mu_global);
server->listeners_destroyed++;
maybe_finish_shutdown(server);
gpr_mu_unlock(&server->mu_global);
} }
void grpc_server_cancel_all_calls(grpc_server *server) { void grpc_server_cancel_all_calls(grpc_server *server) {
channel_broadcaster broadcaster; channel_broadcaster broadcaster;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_mu_lock(&server->mu_global); gpr_mu_lock(&server->mu_global);
channel_broadcaster_init(server, &broadcaster); channel_broadcaster_init(server, &broadcaster);
gpr_mu_unlock(&server->mu_global); 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) { void grpc_server_destroy(grpc_server *server) {
listener *l; listener *l;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
gpr_mu_lock(&server->mu_global); gpr_mu_lock(&server->mu_global);
GPR_ASSERT(gpr_atm_acq_load(&server->shutdown_flag) || !server->listeners); 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); gpr_mu_unlock(&server->mu_global);
grpc_workqueue_flush(server->workqueue); server_unref(server, &call_list);
grpc_call_list_run(&call_list);
server_unref(server);
} }
void grpc_server_add_listener(grpc_server *server, void *arg, void grpc_server_add_listener(
void (*start)(grpc_server *server, void *arg, grpc_server *server, void *arg,
grpc_pollset **pollsets, void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
size_t pollset_count), size_t pollset_count, grpc_call_list *call_list),
void (*destroy)(grpc_server *server, void *arg)) { 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)); listener *l = gpr_malloc(sizeof(listener));
l->arg = arg; l->arg = arg;
l->start = start; 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, 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; call_data *calld = NULL;
request_matcher *request_matcher = NULL; request_matcher *request_matcher = NULL;
int request_id; int request_id;
if (gpr_atm_acq_load(&server->shutdown_flag)) { if (gpr_atm_acq_load(&server->shutdown_flag)) {
fail_call(server, rc); fail_call(server, rc, call_list);
return GRPC_CALL_OK; return GRPC_CALL_OK;
} }
request_id = gpr_stack_lockfree_pop(server->request_freelist); request_id = gpr_stack_lockfree_pop(server->request_freelist);
if (request_id == -1) { if (request_id == -1) {
/* out of request ids: just fail this one */ /* out of request ids: just fail this one */
fail_call(server, rc); fail_call(server, rc, call_list);
return GRPC_CALL_OK; return GRPC_CALL_OK;
} }
switch (rc->type) { switch (rc->type) {
@ -1135,12 +1159,13 @@ static grpc_call_error queue_call_request(grpc_server *server,
grpc_closure_init( grpc_closure_init(
&calld->kill_zombie_closure, kill_zombie, &calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); 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 { } else {
GPR_ASSERT(calld->state == PENDING); GPR_ASSERT(calld->state == PENDING);
calld->state = ACTIVATED; calld->state = ACTIVATED;
gpr_mu_unlock(&calld->mu_state); 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); gpr_mu_lock(&server->mu_call);
} }
@ -1154,13 +1179,16 @@ grpc_call_error grpc_server_request_call(
grpc_metadata_array *initial_metadata, grpc_metadata_array *initial_metadata,
grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag) { 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)); requested_call *rc = gpr_malloc(sizeof(*rc));
GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details, GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
initial_metadata, cq_bound_to_call, initial_metadata, cq_bound_to_call,
cq_for_notification, tag); cq_for_notification, tag);
if (!grpc_cq_is_server_cq(cq_for_notification)) { if (!grpc_cq_is_server_cq(cq_for_notification)) {
gpr_free(rc); 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); grpc_cq_begin_op(cq_for_notification);
details->reserved = NULL; details->reserved = NULL;
@ -1172,7 +1200,10 @@ grpc_call_error grpc_server_request_call(
rc->call = call; rc->call = call;
rc->data.batch.details = details; rc->data.batch.details = details;
rc->data.batch.initial_metadata = initial_metadata; 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( 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_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag) { 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)); requested_call *rc = gpr_malloc(sizeof(*rc));
registered_method *registered_method = rm; registered_method *registered_method = rm;
if (!grpc_cq_is_server_cq(cq_for_notification)) { if (!grpc_cq_is_server_cq(cq_for_notification)) {
gpr_free(rc); 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); grpc_cq_begin_op(cq_for_notification);
rc->type = REGISTERED_CALL; rc->type = REGISTERED_CALL;
@ -1197,12 +1231,16 @@ grpc_call_error grpc_server_request_registered_call(
rc->data.registered.deadline = deadline; rc->data.registered.deadline = deadline;
rc->data.registered.initial_metadata = initial_metadata; rc->data.registered.initial_metadata = initial_metadata;
rc->data.registered.optional_payload = optional_payload; 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, static void publish_registered_or_batch(grpc_call *call, int success, void *tag,
void *tag); grpc_call_list *call_list);
static void publish_was_not_set(grpc_call *call, int success, void *tag) { static void publish_was_not_set(grpc_call *call, int success, void *tag,
grpc_call_list *call_list) {
abort(); 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, 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_completion_func publish = publish_was_not_set;
grpc_ioreq req[2]; grpc_ioreq req[2];
grpc_ioreq *r = req; 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 fill in the metadata array passed by the client, we need to perform
an ioreq op, that should complete immediately. */ 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; *rc->call = calld->call;
calld->cq_new = rc->cq_for_notification; calld->cq_new = rc->cq_for_notification;
switch (rc->type) { 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_INTERNAL_REF(calld->call, "server");
grpc_call_start_ioreq_and_call_back(calld->call, req, (size_t)(r - req), 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; requested_call *rc = req;
grpc_server *server = rc->server; grpc_server *server = rc->server;
@ -1281,10 +1320,11 @@ static void done_request_event(void *req, grpc_cq_completion *c) {
gpr_free(req); 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; *rc->call = NULL;
switch (rc->type) { switch (rc->type) {
case BATCH_CALL: case BATCH_CALL:
@ -1296,11 +1336,11 @@ static void fail_call(grpc_server *server, requested_call *rc) {
} }
server_ref(server); server_ref(server);
grpc_cq_end_op(rc->cq_for_notification, rc->tag, 0, done_request_event, rc, 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, static void publish_registered_or_batch(grpc_call *call, int success, void *prc,
void *prc) { grpc_call_list *call_list) {
grpc_call_element *elem = grpc_call_element *elem =
grpc_call_stack_element(grpc_call_get_call_stack(call), 0); grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
requested_call *rc = prc; 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; channel_data *chand = elem->channel_data;
server_ref(chand->server); server_ref(chand->server);
grpc_cq_end_op(calld->cq_new, rc->tag, success, done_request_event, rc, 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); GRPC_CALL_INTERNAL_UNREF(call, "server", call_list);
} }

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

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

@ -71,7 +71,8 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse( grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing, 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 beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice); gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg; gpr_uint8 *cur = beg;

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

@ -64,7 +64,8 @@ grpc_chttp2_parse_error grpc_chttp2_goaway_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse( grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing, 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 beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice); gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg; gpr_uint8 *cur = beg;

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

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

@ -35,6 +35,7 @@
#define GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_PING_H #define GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_PING_H
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include "src/core/iomgr/iomgr.h"
#include "src/core/transport/chttp2/frame.h" #include "src/core/transport/chttp2/frame.h"
typedef struct { 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_ping_parser *parser, gpr_uint32 length, gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse( grpc_chttp2_parse_error grpc_chttp2_ping_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing, 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 */ #endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_PING_H */

@ -72,7 +72,8 @@ grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse( grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing, 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 beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice); gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg; gpr_uint8 *cur = beg;

@ -36,6 +36,7 @@
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include "src/core/transport/chttp2/frame.h" #include "src/core/transport/chttp2/frame.h"
#include "src/core/iomgr/iomgr.h"
typedef struct { typedef struct {
gpr_uint8 byte; 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_rst_stream_parser *parser, gpr_uint32 length, gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse( grpc_chttp2_parse_error grpc_chttp2_rst_stream_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing, 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 */ #endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_RST_STREAM_H */

@ -139,7 +139,8 @@ grpc_chttp2_parse_error grpc_chttp2_settings_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse( grpc_chttp2_parse_error grpc_chttp2_settings_parser_parse(
void *p, grpc_chttp2_transport_parsing *transport_parsing, 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; grpc_chttp2_settings_parser *parser = p;
const gpr_uint8 *cur = GPR_SLICE_START_PTR(slice); const gpr_uint8 *cur = GPR_SLICE_START_PTR(slice);
const gpr_uint8 *end = GPR_SLICE_END_PTR(slice); const gpr_uint8 *end = GPR_SLICE_END_PTR(slice);

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

@ -75,7 +75,8 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse( grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing, 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 beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *const end = GPR_SLICE_END_PTR(slice); gpr_uint8 *const end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg; gpr_uint8 *cur = beg;

@ -34,6 +34,7 @@
#ifndef GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H #ifndef GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H
#define GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H #define GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H
#include "src/core/iomgr/iomgr.h"
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include "src/core/transport/chttp2/frame.h" #include "src/core/transport/chttp2/frame.h"
@ -51,6 +52,7 @@ grpc_chttp2_parse_error grpc_chttp2_window_update_parser_begin_frame(
gpr_uint8 flags); gpr_uint8 flags);
grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse( grpc_chttp2_parse_error grpc_chttp2_window_update_parser_parse(
void *parser, grpc_chttp2_transport_parsing *transport_parsing, 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 */ #endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_FRAME_WINDOW_UPDATE_H */

@ -1379,7 +1379,8 @@ int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
grpc_chttp2_parse_error grpc_chttp2_header_parser_parse( grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
void *hpack_parser, grpc_chttp2_transport_parsing *transport_parsing, 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; grpc_chttp2_hpack_parser *parser = hpack_parser;
if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice), if (!grpc_chttp2_hpack_parser_parse(parser, GPR_SLICE_START_PTR(slice),
GPR_SLICE_END_PTR(slice))) { GPR_SLICE_END_PTR(slice))) {

@ -37,6 +37,7 @@
#include <stddef.h> #include <stddef.h>
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/iomgr/iomgr.h"
#include "src/core/transport/chttp2/frame.h" #include "src/core/transport/chttp2/frame.h"
#include "src/core/transport/chttp2/hpack_table.h" #include "src/core/transport/chttp2/hpack_table.h"
#include "src/core/transport/metadata.h" #include "src/core/transport/metadata.h"
@ -108,6 +109,7 @@ int grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser *p,
the transport */ the transport */
grpc_chttp2_parse_error grpc_chttp2_header_parser_parse( grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
void *hpack_parser, grpc_chttp2_transport_parsing *transport_parsing, 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 */ #endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_HPACK_PARSER_H */

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

@ -59,7 +59,8 @@ static int init_skip_frame_parser(
grpc_chttp2_transport_parsing *transport_parsing, int is_header); grpc_chttp2_transport_parsing *transport_parsing, int is_header);
static int parse_frame_slice(grpc_chttp2_transport_parsing *transport_parsing, 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( void grpc_chttp2_prepare_to_read(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
@ -90,9 +91,9 @@ void grpc_chttp2_prepare_to_read(
} }
} }
void grpc_chttp2_publish_reads( void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_transport_parsing *transport_parsing) { grpc_call_list *call_list) {
grpc_chttp2_stream_global *stream_global; grpc_chttp2_stream_global *stream_global;
grpc_chttp2_stream_parsing *stream_parsing; grpc_chttp2_stream_parsing *stream_parsing;
@ -132,7 +133,7 @@ void grpc_chttp2_publish_reads(
if (transport_parsing->goaway_received) { if (transport_parsing->goaway_received) {
grpc_chttp2_add_incoming_goaway(transport_global, grpc_chttp2_add_incoming_goaway(transport_global,
(gpr_uint32)transport_parsing->goaway_error, (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_text = gpr_empty_slice();
transport_parsing->goaway_received = 0; 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, 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 *beg = GPR_SLICE_START_PTR(slice);
gpr_uint8 *end = GPR_SLICE_END_PTR(slice); gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
gpr_uint8 *cur = beg; gpr_uint8 *cur = beg;
@ -364,7 +365,8 @@ int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
transport_parsing->incoming_stream_id; transport_parsing->incoming_stream_id;
} }
if (transport_parsing->incoming_frame_size == 0) { 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; return 0;
} }
transport_parsing->incoming_stream = NULL; 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, if (!parse_frame_slice(transport_parsing,
gpr_slice_sub_no_ref(slice, (size_t)(cur - beg), gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
(size_t)(end - beg)), (size_t)(end - beg)),
1)) { 1, call_list)) {
return 0; return 0;
} }
transport_parsing->deframe_state = GRPC_DTS_FH_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( gpr_slice_sub_no_ref(
slice, cur_offset, slice, cur_offset,
cur_offset + transport_parsing->incoming_frame_size), cur_offset + transport_parsing->incoming_frame_size),
1)) { 1, call_list)) {
return 0; return 0;
} }
cur += transport_parsing->incoming_frame_size; 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, if (!parse_frame_slice(transport_parsing,
gpr_slice_sub_no_ref(slice, (size_t)(cur - beg), gpr_slice_sub_no_ref(slice, (size_t)(cur - beg),
(size_t)(end - beg)), (size_t)(end - beg)),
0)) { 0, call_list)) {
return 0; return 0;
} }
transport_parsing->incoming_frame_size -= (gpr_uint32)(end - cur); 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( static grpc_chttp2_parse_error skip_parser(
void *parser, grpc_chttp2_transport_parsing *transport_parsing, 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; 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, 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 = grpc_chttp2_stream_parsing *stream_parsing =
transport_parsing->incoming_stream; transport_parsing->incoming_stream;
switch (transport_parsing->parser(transport_parsing->parser_data, switch (transport_parsing->parser(transport_parsing->parser_data,
transport_parsing, stream_parsing, slice, transport_parsing, stream_parsing, slice,
is_last)) { is_last, call_list)) {
case GRPC_CHTTP2_PARSE_OK: case GRPC_CHTTP2_PARSE_OK:
if (stream_parsing) { if (stream_parsing) {
grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,

@ -163,7 +163,8 @@ int grpc_chttp2_unlocking_check_writes(
} }
void grpc_chttp2_perform_writes( 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 || GPR_ASSERT(transport_writing->outbuf.count > 0 ||
grpc_chttp2_list_have_writing_streams(transport_writing)); 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(transport_writing->outbuf.count > 0);
GPR_ASSERT(endpoint); GPR_ASSERT(endpoint);
switch (grpc_endpoint_write(endpoint, &transport_writing->outbuf, grpc_endpoint_write(endpoint, &transport_writing->outbuf,
&transport_writing->done_cb)) { &transport_writing->done_cb, call_list);
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;
}
} }
static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) { 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( void grpc_chttp2_cleanup_writing(
grpc_chttp2_transport_global *transport_global, 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_writing *stream_writing;
grpc_chttp2_stream_global *stream_global; grpc_chttp2_stream_global *stream_global;
@ -238,8 +231,7 @@ void grpc_chttp2_cleanup_writing(
stream_global->outgoing_sopb->nops == 0) { stream_global->outgoing_sopb->nops == 0) {
GPR_ASSERT(stream_global->write_state != GRPC_WRITE_STATE_QUEUED_CLOSE); GPR_ASSERT(stream_global->write_state != GRPC_WRITE_STATE_QUEUED_CLOSE);
stream_global->outgoing_sopb = NULL; stream_global->outgoing_sopb = NULL;
grpc_call_list_add(&transport_global->run_at_unlock, grpc_call_list_add(call_list, stream_global->send_done_closure, 1);
stream_global->send_done_closure, 1);
} }
} }
stream_global->writing_now = 0; stream_global->writing_now = 0;

@ -78,27 +78,31 @@ int grpc_flowctl_trace = 0;
static const grpc_transport_vtable vtable; static const grpc_transport_vtable vtable;
static void lock(grpc_chttp2_transport *t); 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 */ /* 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 */ /** Set a transport level setting, and push it to our peer */
static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
gpr_uint32 value); gpr_uint32 value);
/** Endpoint callback to process incoming data */ /** 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 */ /** 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 */ /** Perform a transport_op */
static void perform_stream_op_locked( static void perform_stream_op_locked(
grpc_chttp2_transport_global *transport_global, 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 */ /** Cancel a stream: coming from the transport API */
static void cancel_from_api(grpc_chttp2_transport_global *transport_global, 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 */ /** Add endpoint from this transport to pollset */
static void add_to_pollset_locked(grpc_chttp2_transport *t, 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, 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 */ /** Start new streams that have been created if we can */
static void maybe_start_some_streams( 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( static void connectivity_state_set(
grpc_chttp2_transport_global *transport_global, 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 * 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; size_t i;
gpr_mu_lock(&t->mu); 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->parsing_stream_map);
grpc_chttp2_stream_map_destroy(&t->new_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_unlock(&t->mu);
gpr_mu_destroy(&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 */ and maybe they hold resources that need to be freed */
while (t->global.pings.next != &t->global.pings) { while (t->global.pings.next != &t->global.pings) {
grpc_chttp2_outstanding_ping *ping = t->global.pings.next; 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->next->prev = ping->prev;
ping->prev->next = ping->next; ping->prev->next = ping->next;
gpr_free(ping); gpr_free(ping);
@ -180,13 +189,13 @@ static void destruct_transport(grpc_chttp2_transport *t) {
#ifdef REFCOUNTING_DEBUG #ifdef REFCOUNTING_DEBUG
#define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__) #define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__)
#define UNREF_TRANSPORT(t, r) unref_transport(t, r, __FILE__, __LINE__) #define UNREF_TRANSPORT(t, r, cl) unref_transport(t, cl, r, __FILE__, __LINE__)
static void unref_transport(grpc_chttp2_transport *t, const char *reason, static void unref_transport(grpc_chttp2_transport *t, grpc_call_list *call_list,
const char *file, int line) { const char *reason, const char *file, int line) {
gpr_log(GPR_DEBUG, "chttp2:unref:%p %d->%d %s [%s:%d]", t, t->refs.count, gpr_log(GPR_DEBUG, "chttp2:unref:%p %d->%d %s [%s:%d]", t, t->refs.count,
t->refs.count - 1, reason, file, line); t->refs.count - 1, reason, file, line);
if (!gpr_unref(&t->refs)) return; 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, 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 #else
#define REF_TRANSPORT(t, r) ref_transport(t) #define REF_TRANSPORT(t, r) ref_transport(t)
#define UNREF_TRANSPORT(t, r) unref_transport(t) #define UNREF_TRANSPORT(t, r, cl) unref_transport(t, cl)
static void unref_transport(grpc_chttp2_transport *t) { static void unref_transport(grpc_chttp2_transport *t,
grpc_call_list *call_list) {
if (!gpr_unref(&t->refs)) return; 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); } 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, static void init_transport(grpc_chttp2_transport *t,
const grpc_channel_args *channel_args, const grpc_channel_args *channel_args,
grpc_endpoint *ep, grpc_mdctx *mdctx, 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; size_t i;
int j; 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; grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
lock(t); lock(t);
t->destroying = 1; t->destroying = 1;
drop_connection(t); drop_connection(t, call_list);
unlock(t); unlock(t, call_list);
UNREF_TRANSPORT(t, "destroy"); UNREF_TRANSPORT(t, "destroy", call_list);
} }
/** block grpc_endpoint_shutdown being called until a paired /** 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); 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 (gpr_unref(&t->shutdown_ep_refs)) {
if (t->ep) { 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)) { if (gpr_unref(&t->shutdown_ep_refs)) {
gpr_mu_lock(&t->mu); gpr_mu_lock(&t->mu);
if (t->ep) { if (t->ep) {
grpc_endpoint_shutdown(t->ep); grpc_endpoint_shutdown(t->ep, call_list);
} }
gpr_mu_unlock(&t->mu); gpr_mu_unlock(&t->mu);
} }
} }
static void destroy_endpoint(grpc_chttp2_transport *t) { static void destroy_endpoint(grpc_chttp2_transport *t,
grpc_endpoint_destroy(t->ep); grpc_call_list *call_list) {
grpc_endpoint_destroy(t->ep, call_list);
t->ep = NULL; t->ep = NULL;
UNREF_TRANSPORT( /* safe because we'll still have the ref for write */
t, "disconnect"); /* 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) { if (!t->closed) {
t->closed = 1; t->closed = 1;
connectivity_state_set(&t->global, GRPC_CHANNEL_FATAL_FAILURE, connectivity_state_set(&t->global, GRPC_CHANNEL_FATAL_FAILURE,
"close_transport"); "close_transport", call_list);
if (t->ep) { 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, static int init_stream(grpc_transport *gt, grpc_stream *gs,
const void *server_data, 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_transport *t = (grpc_chttp2_transport *)gt;
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; 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; s->global.in_stream_map = 1;
} }
if (initial_op) perform_stream_op_locked(&t->global, &s->global, initial_op); if (initial_op)
unlock(t); perform_stream_op_locked(&t->global, &s->global, initial_op, call_list);
unlock(t, call_list);
return 0; 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_transport *t = (grpc_chttp2_transport *)gt;
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
int i; int i;
@ -433,7 +450,7 @@ static void destroy_stream(grpc_transport *gt, grpc_stream *gs) {
s->global.id == 0); s->global.id == 0);
GPR_ASSERT(!s->global.in_stream_map); GPR_ASSERT(!s->global.in_stream_map);
if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) { 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) { if (!t->parsing_active && s->global.id) {
GPR_ASSERT(grpc_chttp2_stream_map_find(&t->parsing_stream_map, 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( grpc_chttp2_incoming_metadata_live_op_buffer_end(
&s->global.outstanding_metadata); &s->global.outstanding_metadata);
UNREF_TRANSPORT(t, "stream"); UNREF_TRANSPORT(t, "stream", call_list);
} }
grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream( 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 lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); }
static void unlock(grpc_chttp2_transport *t) { static void unlock(grpc_chttp2_transport *t, grpc_call_list *call_list) {
grpc_call_list run = GRPC_CALL_LIST_INIT; unlock_check_read_write_state(t, call_list);
unlock_check_read_write_state(t);
if (!t->writing_active && !t->closed && if (!t->writing_active && !t->closed &&
grpc_chttp2_unlocking_check_writes(&t->global, &t->writing)) { grpc_chttp2_unlocking_check_writes(&t->global, &t->writing)) {
t->writing_active = 1; t->writing_active = 1;
REF_TRANSPORT(t, "writing"); 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); prevent_endpoint_shutdown(t);
} }
GPR_SWAP(grpc_call_list, run, t->global.run_at_unlock);
gpr_mu_unlock(&t->mu); 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_writing *transport_writing = transport_writing_ptr;
grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing);
lock(t); lock(t);
allow_endpoint_shutdown_locked(t); allow_endpoint_shutdown_locked(t, call_list);
if (!success) { if (!success) {
drop_connection(t); drop_connection(t, call_list);
} }
/* cleanup writing related jazz */ /* 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() /* leave the writing flag up on shutdown to prevent further writes in unlock()
from starting */ from starting */
t->writing_active = 0; t->writing_active = 0;
if (t->ep && !t->endpoint_reading) { 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_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( void grpc_chttp2_add_incoming_goaway(
grpc_chttp2_transport_global *transport_global, gpr_uint32 goaway_error, 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); 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_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg);
gpr_free(msg); gpr_free(msg);
gpr_slice_unref(goaway_text); gpr_slice_unref(goaway_text);
transport_global->seen_goaway = 1; transport_global->seen_goaway = 1;
connectivity_state_set(transport_global, GRPC_CHANNEL_FATAL_FAILURE, connectivity_state_set(transport_global, GRPC_CHANNEL_FATAL_FAILURE,
"got_goaway"); "got_goaway", call_list);
} }
static void maybe_start_some_streams( 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; grpc_chttp2_stream_global *stream_global;
/* start streams where we have free grpc_chttp2_stream ids and free /* start streams where we have free grpc_chttp2_stream ids and free
* concurrency */ * concurrency */
@ -601,7 +616,7 @@ static void maybe_start_some_streams(
if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) { if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) {
connectivity_state_set(transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE, connectivity_state_set(transport_global, GRPC_CHANNEL_TRANSIENT_FAILURE,
"no_more_stream_ids"); "no_more_stream_ids", call_list);
} }
stream_global->outgoing_window = stream_global->outgoing_window =
@ -631,7 +646,8 @@ static void maybe_start_some_streams(
static void perform_stream_op_locked( static void perform_stream_op_locked(
grpc_chttp2_transport_global *transport_global, 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) { if (op->cancel_with_status != GRPC_STATUS_OK) {
cancel_from_api(transport_global, stream_global, op->cancel_with_status); 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)); transport_global->is_client ? "CLI" : "SVR", stream_global));
grpc_chttp2_list_add_waiting_for_concurrency(transport_global, grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
stream_global); stream_global);
maybe_start_some_streams(transport_global); maybe_start_some_streams(transport_global, call_list);
} else if (stream_global->outgoing_window > 0) { } else if (stream_global->outgoing_window > 0) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global); grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
} }
} else { } else {
grpc_sopb_reset(op->send_ops); grpc_sopb_reset(op->send_ops);
grpc_call_list_add(&transport_global->run_at_unlock, grpc_call_list_add(call_list, stream_global->send_done_closure, 0);
stream_global->send_done_closure, 0);
} }
} }
@ -700,20 +715,21 @@ static void perform_stream_op_locked(
if (op->bind_pollset) { if (op->bind_pollset) {
add_to_pollset_locked(TRANSPORT_FROM_GLOBAL(transport_global), 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, 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_transport *t = (grpc_chttp2_transport *)gt;
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
lock(t); lock(t);
perform_stream_op_locked(&t->global, &s->global, op); perform_stream_op_locked(&t->global, &s->global, op, call_list);
unlock(t); unlock(t, call_list);
} }
static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) { 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)); 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; grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
int close_transport = 0; int close_transport = 0;
lock(t); 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) { if (op->on_connectivity_state_change) {
grpc_connectivity_state_notify_on_state_change( grpc_connectivity_state_notify_on_state_change(
&t->channel_callback.state_tracker, op->connectivity_state, &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) { if (op->send_goaway) {
@ -763,11 +780,11 @@ static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
} }
if (op->bind_pollset) { 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) { 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) { if (op->send_ping) {
@ -775,15 +792,15 @@ static void perform_transport_op(grpc_transport *gt, grpc_transport_op *op) {
} }
if (op->disconnect) { if (op->disconnect) {
close_transport_locked(t); close_transport_locked(t, call_list);
} }
unlock(t); unlock(t, call_list);
if (close_transport) { if (close_transport) {
lock(t); lock(t);
close_transport_locked(t); close_transport_locked(t, call_list);
unlock(t); unlock(t, call_list);
} }
} }
@ -799,7 +816,8 @@ static grpc_stream_state compute_state(gpr_uint8 write_closed,
return GRPC_STREAM_OPEN; 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; size_t new_stream_count;
grpc_chttp2_stream *s = grpc_chttp2_stream *s =
grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id); 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); grpc_chttp2_parsing_become_skip_parser(&t->parsing);
} }
if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) { 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) + 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); GPR_ASSERT(new_stream_count <= GPR_UINT32_MAX);
if (new_stream_count != t->global.concurrent_stream_count) { if (new_stream_count != t->global.concurrent_stream_count) {
t->global.concurrent_stream_count = (gpr_uint32)new_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_transport_global *transport_global = &t->global;
grpc_chttp2_stream_global *stream_global; grpc_chttp2_stream_global *stream_global;
grpc_stream_state state; 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->in_stream_map);
GPR_ASSERT(stream_global->write_state != GRPC_WRITE_STATE_OPEN); GPR_ASSERT(stream_global->write_state != GRPC_WRITE_STATE_OPEN);
GPR_ASSERT(stream_global->read_closed); 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, grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global); stream_global);
} }
@ -866,8 +885,7 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
if (stream_global->outgoing_sopb != NULL) { if (stream_global->outgoing_sopb != NULL) {
grpc_sopb_reset(stream_global->outgoing_sopb); grpc_sopb_reset(stream_global->outgoing_sopb);
stream_global->outgoing_sopb = NULL; stream_global->outgoing_sopb = NULL;
grpc_call_list_add(&transport_global->run_at_unlock, grpc_call_list_add(call_list, stream_global->send_done_closure, 1);
stream_global->send_done_closure, 1);
} }
stream_global->read_closed = 1; stream_global->read_closed = 1;
if (!stream_global->published_cancelled) { 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, grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global,
stream_global); stream_global);
} else { } else {
remove_stream(t, stream_global->id); remove_stream(t, stream_global->id, call_list);
} }
} }
if (!stream_global->publish_sopb) { if (!stream_global->publish_sopb) {
@ -917,8 +935,7 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
&stream_global->outstanding_metadata); &stream_global->outstanding_metadata);
grpc_sopb_swap(stream_global->publish_sopb, &stream_global->incoming_sopb); grpc_sopb_swap(stream_global->publish_sopb, &stream_global->incoming_sopb);
stream_global->published_state = *stream_global->publish_state = state; stream_global->published_state = *stream_global->publish_state = state;
grpc_call_list_add(&transport_global->run_at_unlock, grpc_call_list_add(call_list, stream_global->recv_done_closure, 1);
stream_global->recv_done_closure, 1);
stream_global->recv_done_closure = NULL; stream_global->recv_done_closure = NULL;
stream_global->publish_sopb = NULL; stream_global->publish_sopb = NULL;
stream_global->publish_state = 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); grpc_chttp2_for_all_streams(&t->global, NULL, cancel_stream_cb);
} }
static void drop_connection(grpc_chttp2_transport *t) { static void drop_connection(grpc_chttp2_transport *t,
close_transport_locked(t); grpc_call_list *call_list) {
close_transport_locked(t, call_list);
end_all_the_calls(t); 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; t->endpoint_reading = 0;
if (!t->writing_active && t->ep) { if (!t->writing_active && t->ep) {
destroy_endpoint(t); destroy_endpoint(t, call_list);
} }
} }
/* tcp read callback */ /* 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; size_t i;
int keep_reading = 0; int keep_reading = 0;
grpc_chttp2_transport *t = tp;
lock(t); lock(t);
i = 0; 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); grpc_chttp2_prepare_to_read(&t->global, &t->parsing);
gpr_mu_unlock(&t->mu); gpr_mu_unlock(&t->mu);
for (; i < t->read_buffer.count && 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++) i++)
; ;
gpr_mu_lock(&t->mu); gpr_mu_lock(&t->mu);
if (i != t->read_buffer.count) { if (i != t->read_buffer.count) {
drop_connection(t); drop_connection(t, call_list);
} }
/* merge stream lists */ /* merge stream lists */
grpc_chttp2_stream_map_move_into(&t->new_stream_map, 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; t->parsing.initial_window_update = 0;
} }
/* handle higher level things */ /* 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; t->parsing_active = 0;
} }
if (!*success || i != t->read_buffer.count) { if (!success || i != t->read_buffer.count) {
drop_connection(t); drop_connection(t, call_list);
read_error_locked(t); read_error_locked(t, call_list);
} else if (!t->closed) { } else if (!t->closed) {
keep_reading = 1; keep_reading = 1;
REF_TRANSPORT(t, "keep_reading"); REF_TRANSPORT(t, "keep_reading");
prevent_endpoint_shutdown(t); prevent_endpoint_shutdown(t);
} }
gpr_slice_buffer_reset_and_unref(&t->read_buffer); gpr_slice_buffer_reset_and_unref(&t->read_buffer);
unlock(t); unlock(t, call_list);
if (keep_reading) { if (keep_reading) {
int ret = -1; grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data, call_list);
switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) { allow_endpoint_shutdown_unlocked(t, call_list);
case GRPC_ENDPOINT_DONE: UNREF_TRANSPORT(t, "keep_reading", call_list);
*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;
} else { } else {
UNREF_TRANSPORT(t, "recv_data"); UNREF_TRANSPORT(t, "recv_data", call_list);
return 0;
} }
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( static void connectivity_state_set(
grpc_chttp2_transport_global *transport_global, 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( GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_DEBUG, "set connectivity_state=%d", state)); gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
grpc_connectivity_state_set( grpc_connectivity_state_set(
&TRANSPORT_FROM_GLOBAL(transport_global)->channel_callback.state_tracker, &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, static void add_to_pollset_locked(grpc_chttp2_transport *t,
grpc_pollset *pollset) { grpc_pollset *pollset,
grpc_call_list *call_list) {
if (t->ep) { 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, 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) { 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 * 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); 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( grpc_transport *grpc_create_chttp2_transport(
const grpc_channel_args *channel_args, grpc_endpoint *ep, grpc_mdctx *mdctx, 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)); 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; return &t->base;
} }
void grpc_chttp2_transport_start_reading(grpc_transport *transport, 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; grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */ REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */
gpr_slice_buffer_addn(&t->read_buffer, slices, nslices); gpr_slice_buffer_addn(&t->read_buffer, slices, nslices);
recv_data(t, 1); recv_data(t, 1, call_list);
} }

@ -42,9 +42,10 @@ extern int grpc_flowctl_trace;
grpc_transport *grpc_create_chttp2_transport( grpc_transport *grpc_create_chttp2_transport(
const grpc_channel_args *channel_args, grpc_endpoint *ep, 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, 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 */ #endif /* GRPC_INTERNAL_CORE_TRANSPORT_CHTTP2_TRANSPORT_H */

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

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

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

@ -136,7 +136,8 @@ size_t grpc_transport_stream_size(grpc_transport *transport);
supplied from the accept_stream callback function */ supplied from the accept_stream callback function */
int grpc_transport_init_stream(grpc_transport *transport, grpc_stream *stream, int grpc_transport_init_stream(grpc_transport *transport, grpc_stream *stream,
const void *server_data, 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. /* 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 stream - the grpc_stream to destroy (memory is still owned by the
caller, but any child memory must be cleaned up) */ caller, but any child memory must be cleaned up) */
void grpc_transport_destroy_stream(grpc_transport *transport, 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, void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
grpc_status_code status); 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 */ op - a grpc_transport_stream_op specifying the op to perform */
void grpc_transport_perform_stream_op(grpc_transport *transport, void grpc_transport_perform_stream_op(grpc_transport *transport,
grpc_stream *stream, 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, void grpc_transport_perform_op(grpc_transport *transport, grpc_transport_op *op,
grpc_transport_op *op); grpc_call_list *call_list);
/* Send a ping on a transport /* 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); void grpc_transport_close(grpc_transport *transport);
/* Destroy the 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 */ /* 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 */ #endif /* GRPC_INTERNAL_CORE_TRANSPORT_TRANSPORT_H */

@ -44,23 +44,27 @@ typedef struct grpc_transport_vtable {
/* implementation of grpc_transport_init_stream */ /* implementation of grpc_transport_init_stream */
int (*init_stream)(grpc_transport *self, grpc_stream *stream, int (*init_stream)(grpc_transport *self, grpc_stream *stream,
const void *server_data, 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 */ /* implementation of grpc_transport_perform_stream_op */
void (*perform_stream_op)(grpc_transport *self, grpc_stream *stream, 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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; } grpc_transport_vtable;
/* an instance of a grpc transport */ /* an instance of a grpc transport */

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

@ -44,7 +44,7 @@
static void channel_init_func(grpc_channel_element *elem, grpc_channel *master, static void channel_init_func(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, const grpc_channel_args *args,
grpc_mdctx *metadata_context, int is_first, 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->num_args == 1);
GPR_ASSERT(args->args[0].type == GRPC_ARG_INTEGER); GPR_ASSERT(args->args[0].type == GRPC_ARG_INTEGER);
GPR_ASSERT(0 == strcmp(args->args[0].key, "test_key")); 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, static void call_init_func(grpc_call_element *elem,
const void *server_transport_data, 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->channel_data);
*(int *)(elem->call_data) = 0; *(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); ++*(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); ++*(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); ++*(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) { static void test_create_channel_stack(void) {
const grpc_channel_filter filter = {call_func, channel_func, const grpc_channel_filter filter = {call_func, channel_func,
@ -93,6 +100,7 @@ static void test_create_channel_stack(void) {
grpc_mdctx *metadata_context; grpc_mdctx *metadata_context;
int *channel_data; int *channel_data;
int *call_data; int *call_data;
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
metadata_context = grpc_mdctx_create(); 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)); channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1));
grpc_channel_stack_init(&filters, 1, NULL, &chan_args, metadata_context, grpc_channel_stack_init(&filters, 1, NULL, &chan_args, metadata_context,
channel_stack); channel_stack, &call_list);
GPR_ASSERT(channel_stack->count == 1); GPR_ASSERT(channel_stack->count == 1);
channel_elem = grpc_channel_stack_element(channel_stack, 0); channel_elem = grpc_channel_stack_element(channel_stack, 0);
channel_data = (int *)channel_elem->channel_data; channel_data = (int *)channel_elem->channel_data;
GPR_ASSERT(*channel_data == 0); GPR_ASSERT(*channel_data == 0);
call_stack = gpr_malloc(channel_stack->call_stack_size); 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); GPR_ASSERT(call_stack->count == 1);
call_elem = grpc_call_stack_element(call_stack, 0); call_elem = grpc_call_stack_element(call_stack, 0);
GPR_ASSERT(call_elem->filter == channel_elem->filter); 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(*call_data == 0);
GPR_ASSERT(*channel_data == 1); GPR_ASSERT(*channel_data == 1);
grpc_call_stack_destroy(call_stack); grpc_call_stack_destroy(call_stack, &call_list);
gpr_free(call_stack); gpr_free(call_stack);
GPR_ASSERT(*channel_data == 2); GPR_ASSERT(*channel_data == 2);
grpc_channel_stack_destroy(channel_stack); grpc_channel_stack_destroy(channel_stack, &call_list);
gpr_free(channel_stack); gpr_free(channel_stack);
grpc_mdctx_unref(metadata_context); grpc_mdctx_unref(metadata_context);
GPR_ASSERT(grpc_call_list_empty(call_list));
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {

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

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

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

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

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

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

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

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

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

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

@ -42,14 +42,16 @@ static gpr_timespec test_deadline(void) {
return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(100); 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);
GPR_ASSERT(p->naddrs >= 1); GPR_ASSERT(p->naddrs >= 1);
grpc_resolved_addresses_destroy(p); grpc_resolved_addresses_destroy(p);
gpr_event_set(evp, (void*)1); 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_ASSERT(!p);
gpr_event_set(evp, (void*)1); gpr_event_set(evp, (void*)1);
} }

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

@ -318,7 +318,8 @@ static void check_metadata(expected_md *expected, grpc_credentials_md *md_elems,
static void check_google_iam_metadata(void *user_data, static void check_google_iam_metadata(void *user_data,
grpc_credentials_md *md_elems, grpc_credentials_md *md_elems,
size_t num_md, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status,
grpc_call_list *call_list) {
grpc_credentials *c = (grpc_credentials *)user_data; grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY,
test_google_iam_authorization_token}, 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) { static void test_google_iam_creds(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *creds = grpc_google_iam_credentials_create( grpc_credentials *creds = grpc_google_iam_credentials_create(
test_google_iam_authorization_token, test_google_iam_authority_selector, test_google_iam_authorization_token, test_google_iam_authority_selector,
NULL); NULL);
GPR_ASSERT(grpc_credentials_has_request_metadata(creds)); GPR_ASSERT(grpc_credentials_has_request_metadata(creds));
GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds));
grpc_credentials_get_request_metadata(creds, NULL, test_service_url, 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, static void check_access_token_metadata(void *user_data,
grpc_credentials_md *md_elems, grpc_credentials_md *md_elems,
size_t num_md, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status,
grpc_call_list *call_list) {
grpc_credentials *c = (grpc_credentials *)user_data; grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}}; expected_md emd[] = {{GRPC_AUTHORIZATION_METADATA_KEY, "Bearer blah"}};
GPR_ASSERT(status == GRPC_CREDENTIALS_OK); 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) { 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); 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(creds));
GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds));
GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_OAUTH2) == 0); GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_OAUTH2) == 0);
grpc_credentials_get_request_metadata(creds, NULL, test_service_url, 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( static void check_ssl_oauth2_composite_metadata(void *user_data,
void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_md *md_elems,
grpc_credentials_status status) { size_t num_md,
grpc_credentials_status status,
grpc_call_list *call_list) {
grpc_credentials *c = (grpc_credentials *)user_data; grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = { expected_md emd[] = {
{GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token}}; {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) { static void test_ssl_oauth2_composite_creds(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *ssl_creds = grpc_credentials *ssl_creds =
grpc_ssl_credentials_create(test_root_cert, NULL, NULL); grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
const grpc_credentials_array *creds_array; 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_TYPE_OAUTH2) == 0);
grpc_credentials_get_request_metadata(composite_creds, NULL, test_service_url, grpc_credentials_get_request_metadata(composite_creds, NULL, test_service_url,
check_ssl_oauth2_composite_metadata, 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) { 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( static void check_ssl_oauth2_google_iam_composite_metadata(
void *user_data, grpc_credentials_md *md_elems, size_t num_md, 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; grpc_credentials *c = (grpc_credentials *)user_data;
expected_md emd[] = { expected_md emd[] = {
{GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token}, {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) { static void test_ssl_oauth2_google_iam_composite_creds(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *ssl_creds = grpc_credentials *ssl_creds =
grpc_ssl_credentials_create(test_root_cert, NULL, NULL); grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
const grpc_credentials_array *creds_array; 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_TYPE_IAM) == 0);
grpc_credentials_get_request_metadata( grpc_credentials_get_request_metadata(
composite_creds, NULL, test_service_url, 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( static void on_oauth2_creds_get_metadata_success(void *user_data,
void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_md *md_elems,
grpc_credentials_status status) { size_t num_md,
grpc_credentials_status status,
grpc_call_list *call_list) {
GPR_ASSERT(status == GRPC_CREDENTIALS_OK); GPR_ASSERT(status == GRPC_CREDENTIALS_OK);
GPR_ASSERT(num_md == 1); GPR_ASSERT(num_md == 1);
GPR_ASSERT(gpr_slice_str_cmp(md_elems[0].key, "Authorization") == 0); 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); GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0);
} }
static void on_oauth2_creds_get_metadata_failure( static void on_oauth2_creds_get_metadata_failure(void *user_data,
void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_md *md_elems,
grpc_credentials_status status) { size_t num_md,
grpc_credentials_status status,
grpc_call_list *call_list) {
GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR);
GPR_ASSERT(num_md == 0); GPR_ASSERT(num_md == 0);
GPR_ASSERT(user_data != NULL); GPR_ASSERT(user_data != NULL);
@ -497,39 +516,44 @@ static void validate_compute_engine_http_request(
static int compute_engine_httpcli_get_success_override( static int compute_engine_httpcli_get_success_override(
const grpc_httpcli_request *request, gpr_timespec deadline, 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 = grpc_httpcli_response response =
http_response(200, valid_oauth2_json_response); http_response(200, valid_oauth2_json_response);
validate_compute_engine_http_request(request); validate_compute_engine_http_request(request);
on_response(user_data, &response); on_response(user_data, &response, call_list);
return 1; return 1;
} }
static int compute_engine_httpcli_get_failure_override( static int compute_engine_httpcli_get_failure_override(
const grpc_httpcli_request *request, gpr_timespec deadline, 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."); grpc_httpcli_response response = http_response(403, "Not Authorized.");
validate_compute_engine_http_request(request); validate_compute_engine_http_request(request);
on_response(user_data, &response); on_response(user_data, &response, call_list);
return 1; return 1;
} }
static int httpcli_post_should_not_be_called( static int httpcli_post_should_not_be_called(
const grpc_httpcli_request *request, const char *body_bytes, const grpc_httpcli_request *request, const char *body_bytes,
size_t body_size, gpr_timespec deadline, 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); GPR_ASSERT("HTTP POST should not be called" == NULL);
return 1; return 1;
} }
static int httpcli_get_should_not_be_called( static int httpcli_get_should_not_be_called(
const grpc_httpcli_request *request, gpr_timespec deadline, 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); GPR_ASSERT("HTTP GET should not be called" == NULL);
return 1; return 1;
} }
static void test_compute_engine_creds_success(void) { static void test_compute_engine_creds_success(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *compute_engine_creds = grpc_credentials *compute_engine_creds =
grpc_google_compute_engine_credentials_create(NULL); grpc_google_compute_engine_credentials_create(NULL);
GPR_ASSERT(grpc_credentials_has_request_metadata(compute_engine_creds)); 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); httpcli_post_should_not_be_called);
grpc_credentials_get_request_metadata( grpc_credentials_get_request_metadata(
compute_engine_creds, NULL, test_service_url, 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. */ /* Second request: the cached token should be served directly. */
grpc_httpcli_set_override(httpcli_get_should_not_be_called, grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called); httpcli_post_should_not_be_called);
grpc_credentials_get_request_metadata( grpc_credentials_get_request_metadata(
compute_engine_creds, NULL, test_service_url, 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_credentials_unref(compute_engine_creds);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
} }
static void test_compute_engine_creds_failure(void) { static void test_compute_engine_creds_failure(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *compute_engine_creds = grpc_credentials *compute_engine_creds =
grpc_google_compute_engine_credentials_create(NULL); grpc_google_compute_engine_credentials_create(NULL);
grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override, 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)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(compute_engine_creds));
grpc_credentials_get_request_metadata( grpc_credentials_get_request_metadata(
compute_engine_creds, NULL, test_service_url, 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_credentials_unref(compute_engine_creds);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
static void validate_refresh_token_http_request( 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( static int refresh_token_httpcli_post_success(
const grpc_httpcli_request *request, const char *body, size_t body_size, const grpc_httpcli_request *request, const char *body, size_t body_size,
gpr_timespec deadline, grpc_httpcli_response_cb on_response, gpr_timespec deadline, grpc_httpcli_response_cb on_response,
void *user_data) { void *user_data, grpc_call_list *call_list) {
grpc_httpcli_response response = grpc_httpcli_response response =
http_response(200, valid_oauth2_json_response); http_response(200, valid_oauth2_json_response);
validate_refresh_token_http_request(request, body, body_size); validate_refresh_token_http_request(request, body, body_size);
on_response(user_data, &response); on_response(user_data, &response, call_list);
return 1; return 1;
} }
static int refresh_token_httpcli_post_failure( static int refresh_token_httpcli_post_failure(
const grpc_httpcli_request *request, const char *body, size_t body_size, const grpc_httpcli_request *request, const char *body, size_t body_size,
gpr_timespec deadline, grpc_httpcli_response_cb on_response, 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."); grpc_httpcli_response response = http_response(403, "Not Authorized.");
validate_refresh_token_http_request(request, body, body_size); validate_refresh_token_http_request(request, body, body_size);
on_response(user_data, &response); on_response(user_data, &response, call_list);
return 1; return 1;
} }
static void test_refresh_token_creds_success(void) { static void test_refresh_token_creds_success(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *refresh_token_creds = grpc_credentials *refresh_token_creds =
grpc_google_refresh_token_credentials_create(test_refresh_token_str, grpc_google_refresh_token_credentials_create(test_refresh_token_str,
NULL); NULL);
@ -622,20 +651,24 @@ static void test_refresh_token_creds_success(void) {
refresh_token_httpcli_post_success); refresh_token_httpcli_post_success);
grpc_credentials_get_request_metadata( grpc_credentials_get_request_metadata(
refresh_token_creds, NULL, test_service_url, 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. */ /* Second request: the cached token should be served directly. */
grpc_httpcli_set_override(httpcli_get_should_not_be_called, grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called); httpcli_post_should_not_be_called);
grpc_credentials_get_request_metadata( grpc_credentials_get_request_metadata(
refresh_token_creds, NULL, test_service_url, 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_credentials_unref(refresh_token_creds);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
static void test_refresh_token_creds_failure(void) { static void test_refresh_token_creds_failure(void) {
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *refresh_token_creds = grpc_credentials *refresh_token_creds =
grpc_google_refresh_token_credentials_create(test_refresh_token_str, grpc_google_refresh_token_credentials_create(test_refresh_token_str,
NULL); NULL);
@ -645,9 +678,10 @@ static void test_refresh_token_creds_failure(void) {
GPR_ASSERT(grpc_credentials_has_request_metadata_only(refresh_token_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(refresh_token_creds));
grpc_credentials_get_request_metadata( grpc_credentials_get_request_metadata(
refresh_token_creds, NULL, test_service_url, 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_credentials_unref(refresh_token_creds);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
static void validate_jwt_encode_and_sign_params( 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, static void on_jwt_creds_get_metadata_success(void *user_data,
grpc_credentials_md *md_elems, grpc_credentials_md *md_elems,
size_t num_md, size_t num_md,
grpc_credentials_status status) { grpc_credentials_status status,
grpc_call_list *call_list) {
char *expected_md_value; char *expected_md_value;
gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt); gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt);
GPR_ASSERT(status == GRPC_CREDENTIALS_OK); 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, static void on_jwt_creds_get_metadata_failure(void *user_data,
grpc_credentials_md *md_elems, grpc_credentials_md *md_elems,
size_t num_md, 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(status == GRPC_CREDENTIALS_ERROR);
GPR_ASSERT(num_md == 0); GPR_ASSERT(num_md == 0);
GPR_ASSERT(user_data != NULL); 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) { static void test_jwt_creds_success(void) {
char *json_key_string = test_json_key_str(); char *json_key_string = test_json_key_str();
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *jwt_creds = grpc_credentials *jwt_creds =
grpc_service_account_jwt_access_credentials_create( grpc_service_account_jwt_access_credentials_create(
json_key_string, grpc_max_auth_token_lifetime, NULL); 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_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
grpc_credentials_get_request_metadata(jwt_creds, NULL, test_service_url, grpc_credentials_get_request_metadata(jwt_creds, NULL, test_service_url,
on_jwt_creds_get_metadata_success, 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. */ /* Second request: the cached token should be served directly. */
grpc_jwt_encode_and_sign_set_override( grpc_jwt_encode_and_sign_set_override(
encode_and_sign_jwt_should_not_be_called); encode_and_sign_jwt_should_not_be_called);
grpc_credentials_get_request_metadata(jwt_creds, NULL, test_service_url, grpc_credentials_get_request_metadata(jwt_creds, NULL, test_service_url,
on_jwt_creds_get_metadata_success, 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 /* Third request: Different service url so jwt_encode_and_sign should be
called again (no caching). */ called again (no caching). */
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
grpc_credentials_get_request_metadata(jwt_creds, NULL, other_test_service_url, grpc_credentials_get_request_metadata(jwt_creds, NULL, other_test_service_url,
on_jwt_creds_get_metadata_success, 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); gpr_free(json_key_string);
grpc_credentials_unref(jwt_creds); grpc_credentials_unref(jwt_creds);
@ -755,6 +795,7 @@ static void test_jwt_creds_success(void) {
static void test_jwt_creds_signing_failure(void) { static void test_jwt_creds_signing_failure(void) {
char *json_key_string = test_json_key_str(); char *json_key_string = test_json_key_str();
grpc_call_list call_list = GRPC_CALL_LIST_INIT;
grpc_credentials *jwt_creds = grpc_credentials *jwt_creds =
grpc_service_account_jwt_access_credentials_create( grpc_service_account_jwt_access_credentials_create(
json_key_string, grpc_max_auth_token_lifetime, NULL); 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_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
grpc_credentials_get_request_metadata(jwt_creds, NULL, test_service_url, grpc_credentials_get_request_metadata(jwt_creds, NULL, test_service_url,
on_jwt_creds_get_metadata_failure, on_jwt_creds_get_metadata_failure,
(void *)test_user_data); (void *)test_user_data, &call_list);
gpr_free(json_key_string); gpr_free(json_key_string);
grpc_credentials_unref(jwt_creds); grpc_credentials_unref(jwt_creds);
grpc_jwt_encode_and_sign_set_override(NULL); 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( static void set_google_default_creds_env_var_with_file_contents(

@ -276,14 +276,16 @@ static grpc_httpcli_response http_response(int status, char *body) {
static int httpcli_post_should_not_be_called( static int httpcli_post_should_not_be_called(
const grpc_httpcli_request *request, const char *body_bytes, const grpc_httpcli_request *request, const char *body_bytes,
size_t body_size, gpr_timespec deadline, 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); GPR_ASSERT("HTTP POST should not be called" == NULL);
return 1; return 1;
} }
static int httpcli_get_google_keys_for_email( static int httpcli_get_google_keys_for_email(
const grpc_httpcli_request *request, gpr_timespec deadline, 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()); grpc_httpcli_response response = http_response(200, good_google_email_keys());
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0); 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/" "/robot/v1/metadata/x509/"
"777-abaslkan11hlb6nmim3bpspl31ud@developer." "777-abaslkan11hlb6nmim3bpspl31ud@developer."
"gserviceaccount.com") == 0); "gserviceaccount.com") == 0);
on_response(user_data, &response); on_response(user_data, &response, call_list);
gpr_free(response.body); gpr_free(response.body);
return 1; return 1;
} }
@ -307,6 +309,7 @@ static void on_verification_success(void *user_data,
} }
static void test_jwt_verifier_google_email_issuer_success(void) { 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); grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL; char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer); 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); grpc_auth_json_key_destruct(&key);
GPR_ASSERT(jwt != NULL); GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience, 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); gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier); grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
static int httpcli_get_custom_keys_for_email( static int httpcli_get_custom_keys_for_email(
const grpc_httpcli_request *request, gpr_timespec deadline, 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)); grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
GPR_ASSERT(strcmp(request->host, "keys.bar.com") == 0); GPR_ASSERT(strcmp(request->host, "keys.bar.com") == 0);
GPR_ASSERT(strcmp(request->path, "/jwk/foo@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); gpr_free(response.body);
return 1; return 1;
} }
static void test_jwt_verifier_custom_email_issuer_success(void) { 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); grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(&custom_mapping, 1);
char *jwt = NULL; char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_custom_email_issuer); 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); grpc_auth_json_key_destruct(&key);
GPR_ASSERT(jwt != NULL); GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience, 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); gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier); grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
static int httpcli_get_jwk_set(const grpc_httpcli_request *request, static int httpcli_get_jwk_set(const grpc_httpcli_request *request,
gpr_timespec deadline, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, 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)); grpc_httpcli_response response = http_response(200, gpr_strdup(good_jwk_set));
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0); GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
GPR_ASSERT(strcmp(request->path, "/oauth2/v3/certs") == 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); gpr_free(response.body);
return 1; 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, static int httpcli_get_openid_config(const grpc_httpcli_request *request,
gpr_timespec deadline, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, grpc_httpcli_response_cb on_response,
void *user_data) { void *user_data,
grpc_call_list *call_list) {
grpc_httpcli_response response = grpc_httpcli_response response =
http_response(200, gpr_strdup(good_openid_config)); http_response(200, gpr_strdup(good_openid_config));
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); 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); GPR_ASSERT(strcmp(request->path, GRPC_OPENID_CONFIG_URL_SUFFIX) == 0);
grpc_httpcli_set_override(httpcli_get_jwk_set, grpc_httpcli_set_override(httpcli_get_jwk_set,
httpcli_post_should_not_be_called); httpcli_post_should_not_be_called);
on_response(user_data, &response); on_response(user_data, &response, call_list);
gpr_free(response.body); gpr_free(response.body);
return 1; return 1;
} }
static void test_jwt_verifier_url_issuer_success(void) { 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); grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL; char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_url_issuer); 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); grpc_auth_json_key_destruct(&key);
GPR_ASSERT(jwt != NULL); GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience, 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); gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier); grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
static void on_verification_key_retrieval_error(void *user_data, 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, static int httpcli_get_bad_json(const grpc_httpcli_request *request,
gpr_timespec deadline, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, grpc_httpcli_response_cb on_response,
void *user_data) { void *user_data, grpc_call_list *call_list) {
grpc_httpcli_response response = grpc_httpcli_response response =
http_response(200, gpr_strdup("{\"bad\": \"stuff\"}")); http_response(200, gpr_strdup("{\"bad\": \"stuff\"}"));
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
on_response(user_data, &response); on_response(user_data, &response, call_list);
gpr_free(response.body); gpr_free(response.body);
return 1; return 1;
} }
static void test_jwt_verifier_url_issuer_bad_config(void) { 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); grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL; char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_url_issuer); 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); GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience, grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
on_verification_key_retrieval_error, on_verification_key_retrieval_error,
(void *)expected_user_data); (void *)expected_user_data, &call_list);
gpr_free(jwt); gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier); grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
static void test_jwt_verifier_bad_json_key(void) { 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); grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL; char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_google_email_issuer); 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); GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience, grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
on_verification_key_retrieval_error, on_verification_key_retrieval_error,
(void *)expected_user_data); (void *)expected_user_data, &call_list);
gpr_free(jwt); gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier); grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
static void corrupt_jwt_sig(char *jwt) { 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) { 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); grpc_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
char *jwt = NULL; char *jwt = NULL;
char *key_str = json_key_str(json_key_str_part3_for_url_issuer); 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); GPR_ASSERT(jwt != NULL);
grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience, grpc_jwt_verifier_verify(verifier, NULL, jwt, expected_audience,
on_verification_bad_signature, on_verification_bad_signature,
(void *)expected_user_data); (void *)expected_user_data, &call_list);
gpr_free(jwt); gpr_free(jwt);
grpc_jwt_verifier_destroy(verifier); grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
static int httpcli_get_should_not_be_called( static int httpcli_get_should_not_be_called(
const grpc_httpcli_request *request, gpr_timespec deadline, 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); GPR_ASSERT(0);
return 1; return 1;
} }
@ -532,14 +552,16 @@ static void on_verification_bad_format(void *user_data,
} }
static void test_jwt_verifier_bad_format(void) { 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_jwt_verifier *verifier = grpc_jwt_verifier_create(NULL, 0);
grpc_httpcli_set_override(httpcli_get_should_not_be_called, grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called); httpcli_post_should_not_be_called);
grpc_jwt_verifier_verify(verifier, NULL, "bad jwt", expected_audience, grpc_jwt_verifier_verify(verifier, NULL, "bad jwt", expected_audience,
on_verification_bad_format, on_verification_bad_format,
(void *)expected_user_data); (void *)expected_user_data, &call_list);
grpc_jwt_verifier_destroy(verifier); grpc_jwt_verifier_destroy(verifier);
grpc_httpcli_set_override(NULL, NULL); grpc_httpcli_set_override(NULL, NULL);
grpc_call_list_run(&call_list);
} }
/* find verification key: bad jks, cannot find key in jks */ /* find verification key: bad jks, cannot find key in jks */

@ -93,7 +93,7 @@ char *grpc_test_fetch_oauth2_token_with_credentials(grpc_credentials *creds) {
while (!request.is_done) { while (!request.is_done) {
grpc_pollset_worker worker; grpc_pollset_worker worker;
grpc_pollset_work(&request.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), 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)); gpr_mu_unlock(GRPC_POLLSET_MU(&request.pollset));

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

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

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

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

Loading…
Cancel
Save