grpc 1.1.2 → 1.2.0.pre1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +1257 -404
  3. data/etc/roots.pem +189 -102
  4. data/include/grpc/census.h +7 -7
  5. data/include/grpc/compression.h +4 -4
  6. data/include/grpc/grpc.h +13 -7
  7. data/include/grpc/impl/codegen/atm_gcc_atomic.h +26 -9
  8. data/include/grpc/impl/codegen/grpc_types.h +39 -30
  9. data/include/grpc/impl/codegen/slice.h +24 -6
  10. data/include/grpc/impl/codegen/sync.h +8 -0
  11. data/include/grpc/load_reporting.h +63 -0
  12. data/include/grpc/slice.h +37 -1
  13. data/include/grpc/slice_buffer.h +7 -0
  14. data/include/grpc/support/alloc.h +3 -0
  15. data/include/grpc/support/useful.h +3 -0
  16. data/src/core/ext/census/gen/census.pb.h +1 -1
  17. data/src/core/ext/census/gen/trace_context.pb.c +9 -36
  18. data/src/core/ext/census/gen/trace_context.pb.h +20 -26
  19. data/src/core/ext/census/grpc_filter.c +3 -5
  20. data/src/core/ext/census/trace_context.c +1 -1
  21. data/src/core/ext/census/trace_context.h +3 -0
  22. data/src/core/ext/census/trace_label.h +61 -0
  23. data/src/core/ext/census/trace_propagation.h +63 -0
  24. data/src/core/ext/census/trace_status.h +45 -0
  25. data/src/core/ext/census/trace_string.h +50 -0
  26. data/src/core/ext/census/tracing.c +31 -11
  27. data/src/core/ext/census/tracing.h +124 -0
  28. data/src/core/ext/client_channel/client_channel.c +456 -368
  29. data/src/core/ext/client_channel/client_channel.h +4 -0
  30. data/src/core/ext/client_channel/client_channel_plugin.c +6 -1
  31. data/src/core/ext/client_channel/connector.c +3 -3
  32. data/src/core/ext/client_channel/connector.h +4 -3
  33. data/src/core/ext/client_channel/http_connect_handshaker.c +62 -72
  34. data/src/core/ext/client_channel/http_connect_handshaker.h +7 -10
  35. data/src/core/ext/client_channel/http_proxy.c +125 -0
  36. data/src/core/ext/client_channel/http_proxy.h +39 -0
  37. data/src/core/ext/client_channel/lb_policy.c +56 -35
  38. data/src/core/ext/client_channel/lb_policy.h +46 -39
  39. data/src/core/ext/client_channel/lb_policy_factory.h +1 -0
  40. data/src/core/ext/client_channel/parse_address.c +32 -6
  41. data/src/core/ext/client_channel/proxy_mapper.c +63 -0
  42. data/src/core/ext/client_channel/proxy_mapper.h +89 -0
  43. data/src/core/ext/client_channel/proxy_mapper_registry.c +133 -0
  44. data/src/core/ext/client_channel/proxy_mapper_registry.h +59 -0
  45. data/src/core/ext/client_channel/resolver.c +16 -9
  46. data/src/core/ext/client_channel/resolver.h +23 -12
  47. data/src/core/ext/client_channel/resolver_factory.h +1 -0
  48. data/src/core/ext/client_channel/resolver_registry.c +15 -11
  49. data/src/core/ext/client_channel/resolver_registry.h +5 -3
  50. data/src/core/ext/client_channel/subchannel.c +44 -27
  51. data/src/core/ext/client_channel/subchannel.h +6 -2
  52. data/src/core/ext/client_channel/uri_parser.c +26 -14
  53. data/src/core/ext/client_channel/uri_parser.h +3 -1
  54. data/src/core/ext/lb_policy/grpclb/grpclb.c +220 -209
  55. data/src/core/ext/lb_policy/grpclb/grpclb_channel.h +56 -0
  56. data/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c +107 -0
  57. data/src/core/ext/lb_policy/grpclb/load_balancer_api.c +3 -6
  58. data/src/core/ext/lb_policy/pick_first/pick_first.c +71 -116
  59. data/src/core/ext/lb_policy/round_robin/round_robin.c +52 -67
  60. data/src/core/ext/load_reporting/load_reporting.c +20 -0
  61. data/src/core/ext/load_reporting/load_reporting.h +1 -16
  62. data/src/core/ext/load_reporting/load_reporting_filter.c +28 -54
  63. data/src/core/ext/resolver/dns/native/dns_resolver.c +31 -45
  64. data/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +20 -29
  65. data/src/core/ext/transport/chttp2/client/chttp2_connector.c +11 -8
  66. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +11 -2
  67. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +143 -46
  68. data/src/core/ext/transport/chttp2/server/chttp2_server.c +12 -50
  69. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +1 -1
  70. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +1 -1
  71. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +7 -7
  72. data/src/core/ext/transport/chttp2/transport/bin_encoder.c +1 -2
  73. data/src/core/ext/transport/chttp2/transport/bin_encoder.h +1 -2
  74. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.c +0 -3
  75. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +606 -374
  76. data/src/core/ext/transport/chttp2/transport/frame_ping.c +17 -5
  77. data/src/core/ext/transport/chttp2/transport/frame_ping.h +2 -2
  78. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +9 -13
  79. data/src/core/ext/transport/chttp2/transport/frame_settings.c +12 -11
  80. data/src/core/ext/transport/chttp2/transport/frame_settings.h +1 -1
  81. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +5 -6
  82. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +100 -53
  83. data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +2 -2
  84. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +126 -70
  85. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +13 -7
  86. data/src/core/ext/transport/chttp2/transport/hpack_table.c +22 -19
  87. data/src/core/ext/transport/chttp2/transport/hpack_table.h +6 -6
  88. data/src/core/ext/transport/chttp2/transport/incoming_metadata.c +23 -11
  89. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +6 -2
  90. data/src/core/ext/transport/chttp2/transport/internal.h +169 -42
  91. data/src/core/ext/transport/chttp2/transport/parsing.c +98 -41
  92. data/src/core/ext/transport/chttp2/transport/stream_lists.c +29 -14
  93. data/src/core/ext/transport/chttp2/transport/writing.c +137 -15
  94. data/src/core/lib/channel/channel_stack.c +14 -44
  95. data/src/core/lib/channel/channel_stack.h +10 -17
  96. data/src/core/lib/channel/channel_stack_builder.c +2 -3
  97. data/src/core/lib/channel/compress_filter.c +54 -46
  98. data/src/core/lib/channel/connected_channel.c +4 -4
  99. data/src/core/lib/channel/connected_channel.h +5 -0
  100. data/src/core/lib/channel/context.h +3 -0
  101. data/src/core/lib/channel/deadline_filter.c +61 -61
  102. data/src/core/lib/channel/deadline_filter.h +8 -5
  103. data/src/core/lib/channel/handshaker.c +47 -7
  104. data/src/core/lib/channel/handshaker.h +21 -3
  105. data/src/core/lib/channel/http_client_filter.c +149 -99
  106. data/src/core/lib/channel/http_server_filter.c +163 -147
  107. data/src/core/lib/channel/message_size_filter.c +15 -10
  108. data/src/core/lib/compression/algorithm_metadata.h +4 -4
  109. data/src/core/lib/compression/compression.c +17 -23
  110. data/src/core/lib/http/httpcli.c +3 -2
  111. data/src/core/lib/http/httpcli.h +2 -1
  112. data/src/core/lib/http/httpcli_security_connector.c +2 -3
  113. data/src/core/lib/http/parser.c +2 -2
  114. data/src/core/lib/iomgr/closure.c +6 -3
  115. data/src/core/lib/iomgr/closure.h +4 -2
  116. data/src/core/lib/iomgr/combiner.c +35 -5
  117. data/src/core/lib/iomgr/combiner.h +21 -2
  118. data/src/core/lib/iomgr/endpoint.c +3 -2
  119. data/src/core/lib/iomgr/endpoint.h +3 -2
  120. data/src/core/lib/iomgr/error.c +60 -94
  121. data/src/core/lib/iomgr/error.h +7 -10
  122. data/src/core/lib/iomgr/error_internal.h +54 -0
  123. data/src/core/lib/iomgr/ev_epoll_linux.c +253 -109
  124. data/src/core/lib/iomgr/ev_poll_posix.c +61 -29
  125. data/src/core/lib/iomgr/ev_posix.c +7 -8
  126. data/src/core/lib/iomgr/ev_posix.h +4 -4
  127. data/src/core/lib/iomgr/exec_ctx.c +11 -6
  128. data/src/core/lib/iomgr/exec_ctx.h +11 -14
  129. data/src/core/lib/iomgr/executor.c +2 -2
  130. data/src/core/lib/iomgr/load_file.c +1 -1
  131. data/src/core/lib/iomgr/network_status_tracker.c +5 -81
  132. data/src/core/lib/iomgr/pollset.h +1 -3
  133. data/src/core/lib/iomgr/pollset_set.h +2 -1
  134. data/src/core/lib/iomgr/pollset_set_uv.c +2 -1
  135. data/src/core/lib/iomgr/pollset_set_windows.c +2 -1
  136. data/src/core/lib/iomgr/pollset_uv.c +25 -11
  137. data/src/core/lib/iomgr/pollset_windows.c +0 -11
  138. data/src/core/lib/iomgr/resolve_address_uv.c +50 -2
  139. data/src/core/lib/iomgr/resource_quota.c +41 -11
  140. data/src/core/lib/iomgr/resource_quota.h +6 -0
  141. data/src/core/lib/iomgr/sockaddr_utils.c +33 -17
  142. data/src/core/lib/iomgr/sockaddr_utils.h +4 -0
  143. data/src/core/lib/iomgr/tcp_client_posix.c +2 -3
  144. data/src/core/lib/iomgr/tcp_client_uv.c +1 -3
  145. data/src/core/lib/iomgr/tcp_client_windows.c +21 -6
  146. data/src/core/lib/iomgr/tcp_posix.c +4 -5
  147. data/src/core/lib/iomgr/tcp_server_posix.c +269 -94
  148. data/src/core/lib/iomgr/tcp_server_windows.c +1 -1
  149. data/src/core/lib/iomgr/tcp_uv.c +11 -5
  150. data/src/core/lib/iomgr/tcp_windows.c +20 -7
  151. data/src/core/lib/iomgr/timer_generic.c +15 -22
  152. data/src/core/lib/iomgr/timer_generic.h +1 -1
  153. data/src/core/lib/iomgr/timer_uv.c +10 -6
  154. data/src/core/lib/iomgr/timer_uv.h +1 -1
  155. data/src/core/lib/iomgr/udp_server.c +45 -6
  156. data/src/core/lib/iomgr/udp_server.h +7 -1
  157. data/src/core/lib/iomgr/unix_sockets_posix.c +11 -1
  158. data/src/core/lib/json/json.c +1 -2
  159. data/src/core/lib/profiling/basic_timers.c +17 -3
  160. data/src/core/lib/security/context/security_context.c +3 -10
  161. data/src/core/lib/security/credentials/composite/composite_credentials.c +4 -8
  162. data/src/core/lib/security/credentials/credentials.c +48 -2
  163. data/src/core/lib/security/credentials/credentials.h +13 -0
  164. data/src/core/lib/security/credentials/credentials_metadata.c +1 -2
  165. data/src/core/lib/security/credentials/fake/fake_credentials.c +6 -8
  166. data/src/core/lib/security/credentials/fake/fake_credentials.h +15 -0
  167. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +3 -3
  168. data/src/core/lib/security/credentials/iam/iam_credentials.c +1 -2
  169. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -2
  170. data/src/core/lib/security/credentials/jwt/jwt_verifier.c +5 -8
  171. data/src/core/lib/security/credentials/jwt/jwt_verifier.h +2 -1
  172. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +3 -5
  173. data/src/core/lib/security/credentials/plugin/plugin_credentials.c +15 -13
  174. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +2 -4
  175. data/src/core/lib/security/transport/client_auth_filter.c +72 -47
  176. data/src/core/lib/security/transport/lb_targets_info.c +70 -0
  177. data/src/core/lib/security/transport/lb_targets_info.h +47 -0
  178. data/src/core/lib/security/transport/secure_endpoint.c +3 -3
  179. data/src/core/lib/security/transport/security_connector.c +125 -28
  180. data/src/core/lib/security/transport/security_connector.h +4 -3
  181. data/src/core/lib/security/transport/security_handshaker.c +13 -9
  182. data/src/core/lib/security/transport/server_auth_filter.c +31 -40
  183. data/src/core/lib/security/util/b64.c +1 -1
  184. data/src/core/lib/slice/slice.c +110 -20
  185. data/src/core/lib/slice/slice_buffer.c +92 -39
  186. data/src/core/lib/{transport/mdstr_hash_table.c → slice/slice_hash_table.c} +40 -33
  187. data/src/core/lib/{transport/mdstr_hash_table.h → slice/slice_hash_table.h} +21 -21
  188. data/src/core/lib/slice/slice_intern.c +346 -0
  189. data/src/core/lib/slice/slice_internal.h +15 -0
  190. data/src/core/lib/slice/slice_string_helpers.c +5 -0
  191. data/src/core/lib/slice/slice_string_helpers.h +5 -0
  192. data/src/core/lib/support/alloc.c +26 -1
  193. data/src/core/lib/support/cmdline.c +2 -4
  194. data/src/core/lib/support/cpu_posix.c +2 -7
  195. data/src/core/lib/support/histogram.c +1 -2
  196. data/src/core/lib/support/log_posix.c +8 -4
  197. data/src/core/lib/support/spinlock.h +52 -0
  198. data/src/core/lib/support/subprocess_posix.c +1 -2
  199. data/src/core/lib/support/sync.c +7 -1
  200. data/src/core/lib/support/sync_posix.c +9 -0
  201. data/src/core/lib/support/time_windows.c +7 -1
  202. data/src/core/lib/surface/call.c +647 -629
  203. data/src/core/lib/surface/call.h +4 -1
  204. data/src/core/lib/surface/call_details.c +8 -2
  205. data/src/core/lib/surface/call_log_batch.c +17 -6
  206. data/src/core/lib/surface/channel.c +49 -59
  207. data/src/core/lib/surface/channel.h +5 -6
  208. data/src/core/lib/surface/completion_queue.c +16 -45
  209. data/src/core/lib/surface/completion_queue.h +0 -3
  210. data/src/core/lib/surface/init.c +6 -2
  211. data/src/core/lib/surface/init_secure.c +1 -1
  212. data/src/core/lib/surface/lame_client.c +14 -4
  213. data/src/core/lib/surface/server.c +79 -82
  214. data/src/core/lib/surface/validate_metadata.c +46 -15
  215. data/src/core/lib/surface/validate_metadata.h +43 -0
  216. data/src/core/lib/surface/version.c +2 -2
  217. data/src/core/lib/transport/bdp_estimator.c +104 -0
  218. data/src/core/lib/transport/bdp_estimator.h +76 -0
  219. data/src/core/lib/transport/connectivity_state.c +33 -13
  220. data/src/core/lib/transport/connectivity_state.h +15 -5
  221. data/src/core/lib/transport/error_utils.c +124 -0
  222. data/src/core/lib/transport/error_utils.h +56 -0
  223. data/src/core/{ext/transport/chttp2 → lib}/transport/http2_errors.h +18 -18
  224. data/src/core/lib/transport/metadata.c +259 -503
  225. data/src/core/lib/transport/metadata.h +69 -68
  226. data/src/core/lib/transport/metadata_batch.c +183 -63
  227. data/src/core/lib/transport/metadata_batch.h +50 -26
  228. data/src/core/lib/transport/pid_controller.c +28 -8
  229. data/src/core/lib/transport/pid_controller.h +15 -2
  230. data/src/core/lib/transport/service_config.c +21 -18
  231. data/src/core/lib/transport/service_config.h +5 -5
  232. data/src/core/lib/transport/static_metadata.c +753 -112
  233. data/src/core/lib/transport/static_metadata.h +403 -264
  234. data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.c +18 -20
  235. data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.h +9 -10
  236. data/src/core/lib/transport/timeout_encoding.c +11 -9
  237. data/src/core/lib/transport/timeout_encoding.h +3 -1
  238. data/src/core/lib/transport/transport.c +47 -87
  239. data/src/core/lib/transport/transport.h +20 -25
  240. data/src/core/lib/transport/transport_op_string.c +7 -19
  241. data/src/core/lib/tsi/fake_transport_security.c +2 -4
  242. data/src/core/lib/tsi/ssl_transport_security.c +7 -16
  243. data/src/core/lib/tsi/transport_security.c +2 -4
  244. data/src/ruby/ext/grpc/extconf.rb +4 -1
  245. data/src/ruby/ext/grpc/rb_byte_buffer.c +7 -0
  246. data/src/ruby/ext/grpc/rb_byte_buffer.h +3 -0
  247. data/src/ruby/ext/grpc/rb_call.c +47 -46
  248. data/src/ruby/ext/grpc/rb_channel.c +21 -6
  249. data/src/ruby/ext/grpc/rb_compression_options.c +9 -6
  250. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +36 -2
  251. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +59 -8
  252. data/src/ruby/ext/grpc/rb_server.c +6 -4
  253. data/src/ruby/lib/grpc/generic/client_stub.rb +1 -1
  254. data/src/ruby/lib/grpc/version.rb +1 -1
  255. metadata +33 -9
@@ -343,7 +343,7 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
343
343
  if (error != GRPC_ERROR_NONE) {
344
344
  const char *msg = grpc_error_string(error);
345
345
  gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg);
346
- grpc_error_free_string(msg);
346
+
347
347
  gpr_mu_unlock(&sp->server->mu);
348
348
  return;
349
349
  }
@@ -79,8 +79,6 @@ typedef struct {
79
79
  grpc_pollset *pollset;
80
80
  } grpc_tcp;
81
81
 
82
- static void uv_close_callback(uv_handle_t *handle) { gpr_free(handle); }
83
-
84
82
  static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
85
83
  grpc_resource_user_unref(exec_ctx, tcp->resource_user);
86
84
  gpr_free(tcp);
@@ -119,6 +117,13 @@ static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
119
117
  static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); }
120
118
  #endif
121
119
 
120
+ static void uv_close_callback(uv_handle_t *handle) {
121
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
122
+ grpc_tcp *tcp = handle->data;
123
+ TCP_UNREF(&exec_ctx, tcp, "destroy");
124
+ grpc_exec_ctx_finish(&exec_ctx);
125
+ }
126
+
122
127
  static void alloc_uv_buf(uv_handle_t *handle, size_t suggested_size,
123
128
  uv_buf_t *buf) {
124
129
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -157,7 +162,7 @@ static void read_callback(uv_stream_t *stream, ssize_t nread,
157
162
  size_t i;
158
163
  const char *str = grpc_error_string(error);
159
164
  gpr_log(GPR_DEBUG, "read: error=%s", str);
160
- grpc_error_free_string(str);
165
+
161
166
  for (i = 0; i < tcp->read_slices->count; i++) {
162
167
  char *dump = grpc_dump_slice(tcp->read_slices->slices[i],
163
168
  GPR_DUMP_HEX | GPR_DUMP_ASCII);
@@ -298,20 +303,21 @@ static void uv_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
298
303
 
299
304
  static void shutdown_callback(uv_shutdown_t *req, int status) {}
300
305
 
301
- static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
306
+ static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
307
+ grpc_error *why) {
302
308
  grpc_tcp *tcp = (grpc_tcp *)ep;
303
309
  if (!tcp->shutting_down) {
304
310
  tcp->shutting_down = true;
305
311
  uv_shutdown_t *req = &tcp->shutdown_req;
306
312
  uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback);
307
313
  }
314
+ GRPC_ERROR_UNREF(why);
308
315
  }
309
316
 
310
317
  static void uv_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
311
318
  grpc_network_status_unregister_endpoint(ep);
312
319
  grpc_tcp *tcp = (grpc_tcp *)ep;
313
320
  uv_close((uv_handle_t *)tcp->handle, uv_close_callback);
314
- TCP_UNREF(exec_ctx, tcp, "destroy");
315
321
  }
316
322
 
317
323
  static char *uv_get_peer(grpc_endpoint *ep) {
@@ -116,6 +116,7 @@ typedef struct grpc_tcp {
116
116
  to protect ourselves when requesting a shutdown. */
117
117
  gpr_mu mu;
118
118
  int shutting_down;
119
+ grpc_error *shutdown_error;
119
120
 
120
121
  char *peer_string;
121
122
  } grpc_tcp;
@@ -125,6 +126,7 @@ static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
125
126
  gpr_mu_destroy(&tcp->mu);
126
127
  gpr_free(tcp->peer_string);
127
128
  grpc_resource_user_unref(exec_ctx, tcp->resource_user);
129
+ if (tcp->shutting_down) GRPC_ERROR_UNREF(tcp->shutdown_error);
128
130
  gpr_free(tcp);
129
131
  }
130
132
 
@@ -182,7 +184,10 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, grpc_error *error) {
182
184
  grpc_slice_buffer_add(tcp->read_slices, sub);
183
185
  } else {
184
186
  grpc_slice_unref_internal(exec_ctx, tcp->read_slice);
185
- error = GRPC_ERROR_CREATE("End of TCP stream");
187
+ error = tcp->shutting_down
188
+ ? GRPC_ERROR_CREATE_REFERENCING("TCP stream shutting down",
189
+ &tcp->shutdown_error, 1)
190
+ : GRPC_ERROR_CREATE("End of TCP stream");
186
191
  }
187
192
  }
188
193
  }
@@ -203,8 +208,9 @@ static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
203
208
  WSABUF buffer;
204
209
 
205
210
  if (tcp->shutting_down) {
206
- grpc_closure_sched(exec_ctx, cb,
207
- GRPC_ERROR_CREATE("TCP socket is shutting down"));
211
+ grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_CREATE_REFERENCING(
212
+ "TCP socket is shutting down",
213
+ &tcp->shutdown_error, 1));
208
214
  return;
209
215
  }
210
216
 
@@ -291,8 +297,9 @@ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
291
297
  size_t len;
292
298
 
293
299
  if (tcp->shutting_down) {
294
- grpc_closure_sched(exec_ctx, cb,
295
- GRPC_ERROR_CREATE("TCP socket is shutting down"));
300
+ grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_CREATE_REFERENCING(
301
+ "TCP socket is shutting down",
302
+ &tcp->shutdown_error, 1));
296
303
  return;
297
304
  }
298
305
 
@@ -373,12 +380,18 @@ static void win_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
373
380
  we're not going to protect against these. However the IO Completion Port
374
381
  callback will happen from another thread, so we need to protect against
375
382
  concurrent access of the data structure in that regard. */
376
- static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
383
+ static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
384
+ grpc_error *why) {
377
385
  grpc_tcp *tcp = (grpc_tcp *)ep;
378
386
  gpr_mu_lock(&tcp->mu);
379
387
  /* At that point, what may happen is that we're already inside the IOCP
380
388
  callback. See the comments in on_read and on_write. */
381
- tcp->shutting_down = 1;
389
+ if (!tcp->shutting_down) {
390
+ tcp->shutting_down = 1;
391
+ tcp->shutdown_error = why;
392
+ } else {
393
+ GRPC_ERROR_UNREF(why);
394
+ }
382
395
  grpc_winsocket_shutdown(tcp->socket);
383
396
  gpr_mu_unlock(&tcp->mu);
384
397
  grpc_resource_user_shutdown(exec_ctx, tcp->resource_user);
@@ -42,6 +42,7 @@
42
42
  #include <grpc/support/useful.h>
43
43
  #include "src/core/lib/iomgr/time_averaged_stats.h"
44
44
  #include "src/core/lib/iomgr/timer_heap.h"
45
+ #include "src/core/lib/support/spinlock.h"
45
46
 
46
47
  #define INVALID_HEAP_INDEX 0xffffffffu
47
48
 
@@ -69,7 +70,7 @@ typedef struct {
69
70
  /* Protects g_shard_queue */
70
71
  static gpr_mu g_mu;
71
72
  /* Allow only one run_some_expired_timers at once */
72
- static gpr_mu g_checker_mu;
73
+ static gpr_spinlock g_checker_mu = GPR_SPINLOCK_STATIC_INITIALIZER;
73
74
  static gpr_clock_type g_clock_type;
74
75
  static shard_type g_shards[NUM_SHARDS];
75
76
  /* Protected by g_mu */
@@ -90,7 +91,6 @@ void grpc_timer_list_init(gpr_timespec now) {
90
91
 
91
92
  g_initialized = true;
92
93
  gpr_mu_init(&g_mu);
93
- gpr_mu_init(&g_checker_mu);
94
94
  g_clock_type = now.clock_type;
95
95
 
96
96
  for (i = 0; i < NUM_SHARDS; i++) {
@@ -117,16 +117,9 @@ void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {
117
117
  grpc_timer_heap_destroy(&shard->heap);
118
118
  }
119
119
  gpr_mu_destroy(&g_mu);
120
- gpr_mu_destroy(&g_checker_mu);
121
120
  g_initialized = false;
122
121
  }
123
122
 
124
- /* This is a cheap, but good enough, pointer hash for sharding the tasks: */
125
- static size_t shard_idx(const grpc_timer *info) {
126
- size_t x = (size_t)info;
127
- return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (NUM_SHARDS - 1);
128
- }
129
-
130
123
  static double ts_to_dbl(gpr_timespec ts) {
131
124
  return (double)ts.tv_sec + 1e-9 * ts.tv_nsec;
132
125
  }
@@ -181,30 +174,30 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
181
174
  gpr_timespec deadline, grpc_closure *closure,
182
175
  gpr_timespec now) {
183
176
  int is_first_timer = 0;
184
- shard_type *shard = &g_shards[shard_idx(timer)];
177
+ shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
185
178
  GPR_ASSERT(deadline.clock_type == g_clock_type);
186
179
  GPR_ASSERT(now.clock_type == g_clock_type);
187
180
  timer->closure = closure;
188
181
  timer->deadline = deadline;
189
- timer->triggered = 0;
190
182
 
191
183
  if (!g_initialized) {
192
- timer->triggered = 1;
184
+ timer->pending = false;
193
185
  grpc_closure_sched(
194
186
  exec_ctx, timer->closure,
195
187
  GRPC_ERROR_CREATE("Attempt to create timer before initialization"));
196
188
  return;
197
189
  }
198
190
 
191
+ gpr_mu_lock(&shard->mu);
192
+ timer->pending = true;
199
193
  if (gpr_time_cmp(deadline, now) <= 0) {
200
- timer->triggered = 1;
194
+ timer->pending = false;
201
195
  grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
196
+ gpr_mu_unlock(&shard->mu);
197
+ /* early out */
202
198
  return;
203
199
  }
204
200
 
205
- /* TODO(ctiller): check deadline expired */
206
-
207
- gpr_mu_lock(&shard->mu);
208
201
  grpc_time_averaged_stats_add_sample(&shard->stats,
209
202
  ts_to_dbl(gpr_time_sub(deadline, now)));
210
203
  if (gpr_time_cmp(deadline, shard->queue_deadline_cap) < 0) {
@@ -247,11 +240,11 @@ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
247
240
  return;
248
241
  }
249
242
 
250
- shard_type *shard = &g_shards[shard_idx(timer)];
243
+ shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
251
244
  gpr_mu_lock(&shard->mu);
252
- if (!timer->triggered) {
245
+ if (timer->pending) {
253
246
  grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
254
- timer->triggered = 1;
247
+ timer->pending = false;
255
248
  if (timer->heap_index == INVALID_HEAP_INDEX) {
256
249
  list_remove(timer);
257
250
  } else {
@@ -302,7 +295,7 @@ static grpc_timer *pop_one(shard_type *shard, gpr_timespec now) {
302
295
  }
303
296
  timer = grpc_timer_heap_top(&shard->heap);
304
297
  if (gpr_time_cmp(timer->deadline, now) > 0) return NULL;
305
- timer->triggered = 1;
298
+ timer->pending = false;
306
299
  grpc_timer_heap_pop(&shard->heap);
307
300
  return timer;
308
301
  }
@@ -330,7 +323,7 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
330
323
 
331
324
  /* TODO(ctiller): verify that there are any timers (atomically) here */
332
325
 
333
- if (gpr_mu_trylock(&g_checker_mu)) {
326
+ if (gpr_spinlock_trylock(&g_checker_mu)) {
334
327
  gpr_mu_lock(&g_mu);
335
328
 
336
329
  while (gpr_time_cmp(g_shard_queue[0]->min_deadline, now) < 0) {
@@ -356,7 +349,7 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
356
349
  }
357
350
 
358
351
  gpr_mu_unlock(&g_mu);
359
- gpr_mu_unlock(&g_checker_mu);
352
+ gpr_spinlock_unlock(&g_checker_mu);
360
353
  } else if (next != NULL) {
361
354
  /* TODO(ctiller): this forces calling code to do an short poll, and
362
355
  then retry the timer check (because this time through the timer list was
@@ -40,7 +40,7 @@
40
40
  struct grpc_timer {
41
41
  gpr_timespec deadline;
42
42
  uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */
43
- int triggered;
43
+ bool pending;
44
44
  struct grpc_timer *next;
45
45
  struct grpc_timer *prev;
46
46
  grpc_closure *closure;
@@ -53,8 +53,8 @@ static void stop_uv_timer(uv_timer_t *handle) {
53
53
  void run_expired_timer(uv_timer_t *handle) {
54
54
  grpc_timer *timer = (grpc_timer *)handle->data;
55
55
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
56
- GPR_ASSERT(!timer->triggered);
57
- timer->triggered = 1;
56
+ GPR_ASSERT(timer->pending);
57
+ timer->pending = 0;
58
58
  grpc_closure_sched(&exec_ctx, timer->closure, GRPC_ERROR_NONE);
59
59
  stop_uv_timer(handle);
60
60
  grpc_exec_ctx_finish(&exec_ctx);
@@ -67,22 +67,26 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
67
67
  uv_timer_t *uv_timer;
68
68
  timer->closure = closure;
69
69
  if (gpr_time_cmp(deadline, now) <= 0) {
70
- timer->triggered = 1;
70
+ timer->pending = 0;
71
71
  grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
72
72
  return;
73
73
  }
74
- timer->triggered = 0;
74
+ timer->pending = 1;
75
75
  timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now));
76
76
  uv_timer = gpr_malloc(sizeof(uv_timer_t));
77
77
  uv_timer_init(uv_default_loop(), uv_timer);
78
78
  uv_timer->data = timer;
79
79
  timer->uv_timer = uv_timer;
80
80
  uv_timer_start(uv_timer, run_expired_timer, timeout, 0);
81
+ /* We assume that gRPC timers are only used alongside other active gRPC
82
+ objects, and that there will therefore always be something else keeping
83
+ the uv loop alive whenever there is a timer */
84
+ uv_unref((uv_handle_t *)uv_timer);
81
85
  }
82
86
 
83
87
  void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
84
- if (!timer->triggered) {
85
- timer->triggered = 1;
88
+ if (timer->pending) {
89
+ timer->pending = 0;
86
90
  grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
87
91
  stop_uv_timer((uv_timer_t *)timer->uv_timer);
88
92
  }
@@ -41,7 +41,7 @@ struct grpc_timer {
41
41
  /* This is actually a uv_timer_t*, but we want to keep platform-specific
42
42
  types out of headers */
43
43
  void *uv_timer;
44
- int triggered;
44
+ int pending;
45
45
  };
46
46
 
47
47
  #endif /* GRPC_CORE_LIB_IOMGR_TIMER_UV_H */
@@ -76,8 +76,10 @@ struct grpc_udp_listener {
76
76
  grpc_udp_server *server;
77
77
  grpc_resolved_address addr;
78
78
  grpc_closure read_closure;
79
+ grpc_closure write_closure;
79
80
  grpc_closure destroyed_closure;
80
81
  grpc_udp_server_read_cb read_cb;
82
+ grpc_udp_server_write_cb write_cb;
81
83
  grpc_udp_server_orphan_cb orphan_cb;
82
84
 
83
85
  struct grpc_udp_listener *next;
@@ -176,7 +178,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
176
178
  /* Call the orphan_cb to signal that the FD is about to be closed and
177
179
  * should no longer be used. */
178
180
  GPR_ASSERT(sp->orphan_cb);
179
- sp->orphan_cb(sp->emfd);
181
+ sp->orphan_cb(exec_ctx, sp->emfd);
180
182
 
181
183
  grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
182
184
  "udp_listener_shutdown");
@@ -202,8 +204,9 @@ void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
202
204
  if (s->active_ports) {
203
205
  for (sp = s->head; sp; sp = sp->next) {
204
206
  GPR_ASSERT(sp->orphan_cb);
205
- sp->orphan_cb(sp->emfd);
206
- grpc_fd_shutdown(exec_ctx, sp->emfd);
207
+ sp->orphan_cb(exec_ctx, sp->emfd);
208
+ grpc_fd_shutdown(exec_ctx, sp->emfd,
209
+ GRPC_ERROR_CREATE("Server destroyed"));
207
210
  }
208
211
  gpr_mu_unlock(&s->mu);
209
212
  } else {
@@ -303,9 +306,33 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
303
306
  gpr_mu_unlock(&sp->server->mu);
304
307
  }
305
308
 
309
+ static void on_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
310
+ grpc_udp_listener *sp = arg;
311
+
312
+ gpr_mu_lock(&(sp->server->mu));
313
+ if (error != GRPC_ERROR_NONE) {
314
+ if (0 == --sp->server->active_ports) {
315
+ gpr_mu_unlock(&sp->server->mu);
316
+ deactivated_all_ports(exec_ctx, sp->server);
317
+ } else {
318
+ gpr_mu_unlock(&sp->server->mu);
319
+ }
320
+ return;
321
+ }
322
+
323
+ /* Tell the registered callback that the socket is writeable. */
324
+ GPR_ASSERT(sp->write_cb);
325
+ sp->write_cb(exec_ctx, sp->emfd);
326
+
327
+ /* Re-arm the notification event so we get another chance to write. */
328
+ grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure);
329
+ gpr_mu_unlock(&sp->server->mu);
330
+ }
331
+
306
332
  static int add_socket_to_server(grpc_udp_server *s, int fd,
307
333
  const grpc_resolved_address *addr,
308
334
  grpc_udp_server_read_cb read_cb,
335
+ grpc_udp_server_write_cb write_cb,
309
336
  grpc_udp_server_orphan_cb orphan_cb) {
310
337
  grpc_udp_listener *sp;
311
338
  int port;
@@ -332,6 +359,7 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
332
359
  sp->emfd = grpc_fd_create(fd, name);
333
360
  memcpy(&sp->addr, addr, sizeof(grpc_resolved_address));
334
361
  sp->read_cb = read_cb;
362
+ sp->write_cb = write_cb;
335
363
  sp->orphan_cb = orphan_cb;
336
364
  GPR_ASSERT(sp->emfd);
337
365
  gpr_mu_unlock(&s->mu);
@@ -344,6 +372,7 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
344
372
  int grpc_udp_server_add_port(grpc_udp_server *s,
345
373
  const grpc_resolved_address *addr,
346
374
  grpc_udp_server_read_cb read_cb,
375
+ grpc_udp_server_write_cb write_cb,
347
376
  grpc_udp_server_orphan_cb orphan_cb) {
348
377
  grpc_udp_listener *sp;
349
378
  int allocated_port1 = -1;
@@ -390,7 +419,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s,
390
419
  // TODO(rjshade): Test and propagate the returned grpc_error*:
391
420
  GRPC_ERROR_UNREF(grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP,
392
421
  &dsmode, &fd));
393
- allocated_port1 = add_socket_to_server(s, fd, addr, read_cb, orphan_cb);
422
+ allocated_port1 =
423
+ add_socket_to_server(s, fd, addr, read_cb, write_cb, orphan_cb);
394
424
  if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
395
425
  goto done;
396
426
  }
@@ -412,7 +442,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s,
412
442
  grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
413
443
  addr = &addr4_copy;
414
444
  }
415
- allocated_port2 = add_socket_to_server(s, fd, addr, read_cb, orphan_cb);
445
+ allocated_port2 =
446
+ add_socket_to_server(s, fd, addr, read_cb, write_cb, orphan_cb);
416
447
 
417
448
  done:
418
449
  gpr_free(allocated_addr);
@@ -450,7 +481,15 @@ void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
450
481
  grpc_schedule_on_exec_ctx);
451
482
  grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
452
483
 
453
- s->active_ports++;
484
+ grpc_closure_init(&sp->write_closure, on_write, sp,
485
+ grpc_schedule_on_exec_ctx);
486
+ grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure);
487
+
488
+ /* Registered for both read and write callbacks: increment active_ports
489
+ * twice to account for this, and delay free-ing of memory until both
490
+ * on_read and on_write have fired. */
491
+ s->active_ports += 2;
492
+
454
493
  sp = sp->next;
455
494
  }
456
495
 
@@ -49,8 +49,13 @@ typedef struct grpc_udp_server grpc_udp_server;
49
49
  typedef void (*grpc_udp_server_read_cb)(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
50
50
  struct grpc_server *server);
51
51
 
52
+ /* Called when the socket is writeable. */
53
+ typedef void (*grpc_udp_server_write_cb)(grpc_exec_ctx *exec_ctx,
54
+ grpc_fd *emfd);
55
+
52
56
  /* Called when the grpc_fd is about to be orphaned (and the FD closed). */
53
- typedef void (*grpc_udp_server_orphan_cb)(grpc_fd *emfd);
57
+ typedef void (*grpc_udp_server_orphan_cb)(grpc_exec_ctx *exec_ctx,
58
+ grpc_fd *emfd);
54
59
 
55
60
  /* Create a server, initially not bound to any ports */
56
61
  grpc_udp_server *grpc_udp_server_create(void);
@@ -75,6 +80,7 @@ int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned port_index);
75
80
  int grpc_udp_server_add_port(grpc_udp_server *s,
76
81
  const grpc_resolved_address *addr,
77
82
  grpc_udp_server_read_cb read_cb,
83
+ grpc_udp_server_write_cb write_cb,
78
84
  grpc_udp_server_orphan_cb orphan_cb);
79
85
 
80
86
  void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *server,