grpc 1.1.2 → 1.2.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -84,6 +84,10 @@ int grpc_sockaddr_set_port(const grpc_resolved_address *addr, int port);
84
84
  int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr,
85
85
  int normalize);
86
86
 
87
+ /* Returns the URI string corresponding to \a addr */
87
88
  char *grpc_sockaddr_to_uri(const grpc_resolved_address *addr);
88
89
 
90
+ /* Returns the URI scheme corresponding to \a addr */
91
+ const char *grpc_sockaddr_get_uri_scheme(const grpc_resolved_address *addr);
92
+
89
93
  #endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */
@@ -118,11 +118,11 @@ static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
118
118
  const char *str = grpc_error_string(error);
119
119
  gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
120
120
  str);
121
- grpc_error_free_string(str);
122
121
  }
123
122
  gpr_mu_lock(&ac->mu);
124
123
  if (ac->fd != NULL) {
125
- grpc_fd_shutdown(exec_ctx, ac->fd);
124
+ grpc_fd_shutdown(exec_ctx, ac->fd,
125
+ GRPC_ERROR_CREATE("connect() timed out"));
126
126
  }
127
127
  done = (--ac->refs == 0);
128
128
  gpr_mu_unlock(&ac->mu);
@@ -178,7 +178,6 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
178
178
  const char *str = grpc_error_string(error);
179
179
  gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s",
180
180
  ac->addr_str, str);
181
- grpc_error_free_string(str);
182
181
  }
183
182
 
184
183
  gpr_mu_lock(&ac->mu);
@@ -76,7 +76,6 @@ static void uv_tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp,
76
76
  const char *str = grpc_error_string(error);
77
77
  gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s",
78
78
  connect->addr_name, str);
79
- grpc_error_free_string(str);
80
79
  }
81
80
  if (error == GRPC_ERROR_NONE) {
82
81
  /* error == NONE implies that the timer ran out, and wasn't cancelled. If
@@ -144,8 +143,7 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
144
143
  }
145
144
  }
146
145
 
147
- connect = gpr_malloc(sizeof(grpc_uv_tcp_connect));
148
- memset(connect, 0, sizeof(grpc_uv_tcp_connect));
146
+ connect = gpr_zalloc(sizeof(grpc_uv_tcp_connect));
149
147
  connect->closure = closure;
150
148
  connect->endpoint = ep;
151
149
  connect->tcp_handle = gpr_malloc(sizeof(uv_tcp_t));
@@ -135,12 +135,10 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
135
135
 
136
136
  /* Tries to issue one async connection, then schedules both an IOCP
137
137
  notification request for the connection, and one timeout alert. */
138
- void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done,
139
- grpc_endpoint **endpoint,
140
- grpc_pollset_set *interested_parties,
141
- const grpc_channel_args *channel_args,
142
- const grpc_resolved_address *addr,
143
- gpr_timespec deadline) {
138
+ static void tcp_client_connect_impl(
139
+ grpc_exec_ctx *exec_ctx, grpc_closure *on_done, grpc_endpoint **endpoint,
140
+ grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args,
141
+ const grpc_resolved_address *addr, gpr_timespec deadline) {
144
142
  SOCKET sock = INVALID_SOCKET;
145
143
  BOOL success;
146
144
  int status;
@@ -252,4 +250,21 @@ failure:
252
250
  grpc_closure_sched(exec_ctx, on_done, final_error);
253
251
  }
254
252
 
253
+ // overridden by api_fuzzer.c
254
+ void (*grpc_tcp_client_connect_impl)(
255
+ grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
256
+ grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args,
257
+ const grpc_resolved_address *addr,
258
+ gpr_timespec deadline) = tcp_client_connect_impl;
259
+
260
+ void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
261
+ grpc_endpoint **ep,
262
+ grpc_pollset_set *interested_parties,
263
+ const grpc_channel_args *channel_args,
264
+ const grpc_resolved_address *addr,
265
+ gpr_timespec deadline) {
266
+ grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties,
267
+ channel_args, addr, deadline);
268
+ }
269
+
255
270
  #endif /* GRPC_WINSOCK_SOCKET */
@@ -119,9 +119,10 @@ static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
119
119
  static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
120
120
  grpc_error *error);
121
121
 
122
- static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
122
+ static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
123
+ grpc_error *why) {
123
124
  grpc_tcp *tcp = (grpc_tcp *)ep;
124
- grpc_fd_shutdown(exec_ctx, tcp->em_fd);
125
+ grpc_fd_shutdown(exec_ctx, tcp->em_fd, why);
125
126
  grpc_resource_user_shutdown(exec_ctx, tcp->resource_user);
126
127
  }
127
128
 
@@ -181,7 +182,7 @@ static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
181
182
  size_t i;
182
183
  const char *str = grpc_error_string(error);
183
184
  gpr_log(GPR_DEBUG, "read: error=%s", str);
184
- grpc_error_free_string(str);
185
+
185
186
  for (i = 0; i < tcp->incoming_buffer->count; i++) {
186
187
  char *dump = grpc_dump_slice(tcp->incoming_buffer->slices[i],
187
188
  GPR_DUMP_HEX | GPR_DUMP_ASCII);
@@ -435,7 +436,6 @@ static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
435
436
  if (grpc_tcp_trace) {
436
437
  const char *str = grpc_error_string(error);
437
438
  gpr_log(GPR_DEBUG, "write: %s", str);
438
- grpc_error_free_string(str);
439
439
  }
440
440
 
441
441
  grpc_closure_run(exec_ctx, cb, error);
@@ -485,7 +485,6 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
485
485
  if (grpc_tcp_trace) {
486
486
  const char *str = grpc_error_string(error);
487
487
  gpr_log(GPR_DEBUG, "write: %s", str);
488
- grpc_error_free_string(str);
489
488
  }
490
489
  grpc_closure_sched(exec_ctx, cb, error);
491
490
  }
@@ -44,6 +44,7 @@
44
44
 
45
45
  #include <errno.h>
46
46
  #include <fcntl.h>
47
+ #include <ifaddrs.h>
47
48
  #include <limits.h>
48
49
  #include <netinet/in.h>
49
50
  #include <netinet/tcp.h>
@@ -113,8 +114,12 @@ struct grpc_tcp_server {
113
114
 
114
115
  /* is this server shutting down? */
115
116
  bool shutdown;
117
+ /* have listeners been shutdown? */
118
+ bool shutdown_listeners;
116
119
  /* use SO_REUSEPORT */
117
120
  bool so_reuseport;
121
+ /* expand wildcard addresses to a list of all local addresses */
122
+ bool expand_wildcard_addrs;
118
123
 
119
124
  /* linked list of server ports */
120
125
  grpc_tcp_listener *head;
@@ -158,9 +163,10 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
158
163
  grpc_tcp_server **server) {
159
164
  gpr_once_init(&check_init, init);
160
165
 
161
- grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
166
+ grpc_tcp_server *s = gpr_zalloc(sizeof(grpc_tcp_server));
162
167
  s->so_reuseport = has_so_reuseport;
163
168
  s->resource_quota = grpc_resource_quota_create(NULL);
169
+ s->expand_wildcard_addrs = false;
164
170
  for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) {
165
171
  if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) {
166
172
  if (args->args[i].type == GRPC_ARG_INTEGER) {
@@ -183,6 +189,15 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
183
189
  return GRPC_ERROR_CREATE(GRPC_ARG_RESOURCE_QUOTA
184
190
  " must be a pointer to a buffer pool");
185
191
  }
192
+ } else if (0 == strcmp(GRPC_ARG_EXPAND_WILDCARD_ADDRS, args->args[i].key)) {
193
+ if (args->args[i].type == GRPC_ARG_INTEGER) {
194
+ s->expand_wildcard_addrs = (args->args[i].value.integer != 0);
195
+ } else {
196
+ grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
197
+ gpr_free(s);
198
+ return GRPC_ERROR_CREATE(GRPC_ARG_EXPAND_WILDCARD_ADDRS
199
+ " must be an integer");
200
+ }
186
201
  }
187
202
  }
188
203
  gpr_ref_init(&s->refs, 1);
@@ -245,10 +260,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
245
260
  /* delete ALL the things */
246
261
  gpr_mu_lock(&s->mu);
247
262
 
248
- if (!s->shutdown) {
249
- gpr_mu_unlock(&s->mu);
250
- return;
251
- }
263
+ GPR_ASSERT(s->shutdown);
252
264
 
253
265
  if (s->head) {
254
266
  grpc_tcp_listener *sp;
@@ -276,7 +288,8 @@ static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
276
288
  if (s->active_ports) {
277
289
  grpc_tcp_listener *sp;
278
290
  for (sp = s->head; sp; sp = sp->next) {
279
- grpc_fd_shutdown(exec_ctx, sp->emfd);
291
+ grpc_fd_shutdown(exec_ctx, sp->emfd,
292
+ GRPC_ERROR_CREATE("Server destroyed"));
280
293
  }
281
294
  gpr_mu_unlock(&s->mu);
282
295
  } else {
@@ -408,7 +421,14 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
408
421
  grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
409
422
  return;
410
423
  default:
411
- gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
424
+ gpr_mu_lock(&sp->server->mu);
425
+ if (!sp->server->shutdown_listeners) {
426
+ gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
427
+ } else {
428
+ /* if we have shutdown listeners, accept4 could fail, and we
429
+ needn't notify users */
430
+ }
431
+ gpr_mu_unlock(&sp->server->mu);
412
432
  goto error;
413
433
  }
414
434
  }
@@ -424,11 +444,6 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
424
444
 
425
445
  grpc_fd *fdobj = grpc_fd_create(fd, name);
426
446
 
427
- if (read_notifier_pollset == NULL) {
428
- gpr_log(GPR_ERROR, "Read notifier pollset is not set on the fd");
429
- goto error;
430
- }
431
-
432
447
  grpc_pollset_add_fd(exec_ctx, read_notifier_pollset, fdobj);
433
448
 
434
449
  // Create acceptor.
@@ -451,7 +466,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
451
466
 
452
467
  error:
453
468
  gpr_mu_lock(&sp->server->mu);
454
- if (0 == --sp->server->active_ports) {
469
+ if (0 == --sp->server->active_ports && sp->server->shutdown) {
455
470
  gpr_mu_unlock(&sp->server->mu);
456
471
  deactivated_all_ports(exec_ctx, sp->server);
457
472
  } else {
@@ -503,9 +518,224 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
503
518
  return err;
504
519
  }
505
520
 
506
- /* Insert count new listeners after listener. Every new listener will have the
507
- same listen address as listener (SO_REUSEPORT must be enabled). Every new
508
- listener is a sibling of listener. */
521
+ /* If successful, add a listener to s for addr, set *dsmode for the socket, and
522
+ return the *listener. */
523
+ static grpc_error *add_addr_to_server(grpc_tcp_server *s,
524
+ const grpc_resolved_address *addr,
525
+ unsigned port_index, unsigned fd_index,
526
+ grpc_dualstack_mode *dsmode,
527
+ grpc_tcp_listener **listener) {
528
+ grpc_resolved_address addr4_copy;
529
+ int fd;
530
+ grpc_error *err =
531
+ grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd);
532
+ if (err != GRPC_ERROR_NONE) {
533
+ return err;
534
+ }
535
+ if (*dsmode == GRPC_DSMODE_IPV4 &&
536
+ grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
537
+ addr = &addr4_copy;
538
+ }
539
+ return add_socket_to_server(s, fd, addr, port_index, fd_index, listener);
540
+ }
541
+
542
+ /* Bind to "::" to get a port number not used by any address. */
543
+ static grpc_error *get_unused_port(int *port) {
544
+ grpc_resolved_address wild;
545
+ grpc_sockaddr_make_wildcard6(0, &wild);
546
+ grpc_dualstack_mode dsmode;
547
+ int fd;
548
+ grpc_error *err =
549
+ grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd);
550
+ if (err != GRPC_ERROR_NONE) {
551
+ return err;
552
+ }
553
+ if (dsmode == GRPC_DSMODE_IPV4) {
554
+ grpc_sockaddr_make_wildcard4(0, &wild);
555
+ }
556
+ if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) {
557
+ err = GRPC_OS_ERROR(errno, "bind");
558
+ close(fd);
559
+ return err;
560
+ }
561
+ if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) !=
562
+ 0) {
563
+ err = GRPC_OS_ERROR(errno, "getsockname");
564
+ close(fd);
565
+ return err;
566
+ }
567
+ close(fd);
568
+ *port = grpc_sockaddr_get_port(&wild);
569
+ return *port <= 0 ? GRPC_ERROR_CREATE("Bad port") : GRPC_ERROR_NONE;
570
+ }
571
+
572
+ /* Return the listener in s with address addr or NULL. */
573
+ static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s,
574
+ grpc_resolved_address *addr) {
575
+ grpc_tcp_listener *l;
576
+ gpr_mu_lock(&s->mu);
577
+ for (l = s->head; l != NULL; l = l->next) {
578
+ if (l->addr.len != addr->len) {
579
+ continue;
580
+ }
581
+ if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) {
582
+ break;
583
+ }
584
+ }
585
+ gpr_mu_unlock(&s->mu);
586
+ return l;
587
+ }
588
+
589
+ /* Get all addresses assigned to network interfaces on the machine and create a
590
+ listener for each. requested_port is the port to use for every listener, or 0
591
+ to select one random port that will be used for every listener. Set *out_port
592
+ to the port selected. Return GRPC_ERROR_NONE only if all listeners were
593
+ added. */
594
+ static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s,
595
+ unsigned port_index,
596
+ int requested_port,
597
+ int *out_port) {
598
+ struct ifaddrs *ifa = NULL;
599
+ struct ifaddrs *ifa_it;
600
+ unsigned fd_index = 0;
601
+ grpc_tcp_listener *sp = NULL;
602
+ grpc_error *err = GRPC_ERROR_NONE;
603
+ if (requested_port == 0) {
604
+ /* Note: There could be a race where some local addrs can listen on the
605
+ selected port and some can't. The sane way to handle this would be to
606
+ retry by recreating the whole grpc_tcp_server. Backing out individual
607
+ listeners and orphaning the FDs looks like too much trouble. */
608
+ if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) {
609
+ return err;
610
+ } else if (requested_port <= 0) {
611
+ return GRPC_ERROR_CREATE("Bad get_unused_port()");
612
+ }
613
+ gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port);
614
+ }
615
+ if (getifaddrs(&ifa) != 0 || ifa == NULL) {
616
+ return GRPC_OS_ERROR(errno, "getifaddrs");
617
+ }
618
+ for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) {
619
+ grpc_resolved_address addr;
620
+ char *addr_str = NULL;
621
+ grpc_dualstack_mode dsmode;
622
+ grpc_tcp_listener *new_sp = NULL;
623
+ const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>");
624
+ if (ifa_it->ifa_addr == NULL) {
625
+ continue;
626
+ } else if (ifa_it->ifa_addr->sa_family == AF_INET) {
627
+ addr.len = sizeof(struct sockaddr_in);
628
+ } else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
629
+ addr.len = sizeof(struct sockaddr_in6);
630
+ } else {
631
+ continue;
632
+ }
633
+ memcpy(addr.addr, ifa_it->ifa_addr, addr.len);
634
+ if (!grpc_sockaddr_set_port(&addr, requested_port)) {
635
+ /* Should never happen, because we check sa_family above. */
636
+ err = GRPC_ERROR_CREATE("Failed to set port");
637
+ break;
638
+ }
639
+ if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) {
640
+ addr_str = gpr_strdup("<error>");
641
+ }
642
+ gpr_log(GPR_DEBUG,
643
+ "Adding local addr from interface %s flags 0x%x to server: %s",
644
+ ifa_name, ifa_it->ifa_flags, addr_str);
645
+ /* We could have multiple interfaces with the same address (e.g., bonding),
646
+ so look for duplicates. */
647
+ if (find_listener_with_addr(s, &addr) != NULL) {
648
+ gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str,
649
+ ifa_name);
650
+ gpr_free(addr_str);
651
+ continue;
652
+ }
653
+ if ((err = add_addr_to_server(s, &addr, port_index, fd_index, &dsmode,
654
+ &new_sp)) != GRPC_ERROR_NONE) {
655
+ char *err_str = NULL;
656
+ grpc_error *root_err;
657
+ if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) {
658
+ err_str = gpr_strdup("Failed to add listener");
659
+ }
660
+ root_err = GRPC_ERROR_CREATE(err_str);
661
+ gpr_free(err_str);
662
+ gpr_free(addr_str);
663
+ err = grpc_error_add_child(root_err, err);
664
+ break;
665
+ } else {
666
+ GPR_ASSERT(requested_port == new_sp->port);
667
+ ++fd_index;
668
+ if (sp != NULL) {
669
+ new_sp->is_sibling = 1;
670
+ sp->sibling = new_sp;
671
+ }
672
+ sp = new_sp;
673
+ }
674
+ gpr_free(addr_str);
675
+ }
676
+ freeifaddrs(ifa);
677
+ if (err != GRPC_ERROR_NONE) {
678
+ return err;
679
+ } else if (sp == NULL) {
680
+ return GRPC_ERROR_CREATE("No local addresses");
681
+ } else {
682
+ *out_port = sp->port;
683
+ return GRPC_ERROR_NONE;
684
+ }
685
+ }
686
+
687
+ /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
688
+ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s,
689
+ unsigned port_index,
690
+ int requested_port,
691
+ int *out_port) {
692
+ grpc_resolved_address wild4;
693
+ grpc_resolved_address wild6;
694
+ unsigned fd_index = 0;
695
+ grpc_dualstack_mode dsmode;
696
+ grpc_tcp_listener *sp = NULL;
697
+ grpc_tcp_listener *sp2 = NULL;
698
+ grpc_error *v6_err = GRPC_ERROR_NONE;
699
+ grpc_error *v4_err = GRPC_ERROR_NONE;
700
+ *out_port = -1;
701
+ if (s->expand_wildcard_addrs) {
702
+ return add_all_local_addrs_to_server(s, port_index, requested_port,
703
+ out_port);
704
+ }
705
+ grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6);
706
+ /* Try listening on IPv6 first. */
707
+ if ((v6_err = add_addr_to_server(s, &wild6, port_index, fd_index, &dsmode,
708
+ &sp)) == GRPC_ERROR_NONE) {
709
+ ++fd_index;
710
+ requested_port = *out_port = sp->port;
711
+ if (dsmode == GRPC_DSMODE_DUALSTACK || dsmode == GRPC_DSMODE_IPV4) {
712
+ return GRPC_ERROR_NONE;
713
+ }
714
+ }
715
+ /* If we got a v6-only socket or nothing, try adding 0.0.0.0. */
716
+ grpc_sockaddr_set_port(&wild4, requested_port);
717
+ if ((v4_err = add_addr_to_server(s, &wild4, port_index, fd_index, &dsmode,
718
+ &sp2)) == GRPC_ERROR_NONE) {
719
+ *out_port = sp2->port;
720
+ if (sp != NULL) {
721
+ sp2->is_sibling = 1;
722
+ sp->sibling = sp2;
723
+ }
724
+ }
725
+ if (*out_port > 0) {
726
+ GRPC_LOG_IF_ERROR("Failed to add :: listener", v6_err);
727
+ GRPC_LOG_IF_ERROR("Failed to add 0.0.0.0 listener", v4_err);
728
+ return GRPC_ERROR_NONE;
729
+ } else {
730
+ grpc_error *root_err =
731
+ GRPC_ERROR_CREATE("Failed to add any wildcard listeners");
732
+ GPR_ASSERT(v6_err != GRPC_ERROR_NONE && v4_err != GRPC_ERROR_NONE);
733
+ root_err = grpc_error_add_child(root_err, v6_err);
734
+ root_err = grpc_error_add_child(root_err, v4_err);
735
+ return root_err;
736
+ }
737
+ }
738
+
509
739
  static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
510
740
  grpc_tcp_listener *sp = NULL;
511
741
  char *addr_str;
@@ -558,19 +788,13 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
558
788
  const grpc_resolved_address *addr,
559
789
  int *out_port) {
560
790
  grpc_tcp_listener *sp;
561
- grpc_tcp_listener *sp2 = NULL;
562
- int fd;
563
- grpc_dualstack_mode dsmode;
564
- grpc_resolved_address addr6_v4mapped;
565
- grpc_resolved_address wild4;
566
- grpc_resolved_address wild6;
567
- grpc_resolved_address addr4_copy;
568
- grpc_resolved_address *allocated_addr = NULL;
569
791
  grpc_resolved_address sockname_temp;
570
- int port;
792
+ grpc_resolved_address addr6_v4mapped;
793
+ int requested_port = grpc_sockaddr_get_port(addr);
571
794
  unsigned port_index = 0;
572
- unsigned fd_index = 0;
573
- grpc_error *errs[2] = {GRPC_ERROR_NONE, GRPC_ERROR_NONE};
795
+ grpc_dualstack_mode dsmode;
796
+ grpc_error *err;
797
+ *out_port = -1;
574
798
  if (s->tail != NULL) {
575
799
  port_index = s->tail->port_index + 1;
576
800
  }
@@ -578,85 +802,34 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
578
802
 
579
803
  /* Check if this is a wildcard port, and if so, try to keep the port the same
580
804
  as some previously created listener. */
581
- if (grpc_sockaddr_get_port(addr) == 0) {
805
+ if (requested_port == 0) {
582
806
  for (sp = s->head; sp; sp = sp->next) {
583
807
  sockname_temp.len = sizeof(struct sockaddr_storage);
584
- if (0 == getsockname(sp->fd, (struct sockaddr *)sockname_temp.addr,
808
+ if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp.addr,
585
809
  (socklen_t *)&sockname_temp.len)) {
586
- port = grpc_sockaddr_get_port(&sockname_temp);
587
- if (port > 0) {
588
- allocated_addr = gpr_malloc(sizeof(grpc_resolved_address));
589
- memcpy(allocated_addr, addr, addr->len);
590
- grpc_sockaddr_set_port(allocated_addr, port);
591
- addr = allocated_addr;
810
+ int used_port = grpc_sockaddr_get_port(&sockname_temp);
811
+ if (used_port > 0) {
812
+ memcpy(&sockname_temp, addr, sizeof(grpc_resolved_address));
813
+ grpc_sockaddr_set_port(&sockname_temp, used_port);
814
+ requested_port = used_port;
815
+ addr = &sockname_temp;
592
816
  break;
593
817
  }
594
818
  }
595
819
  }
596
820
  }
597
-
598
- sp = NULL;
599
-
821
+ if (grpc_sockaddr_is_wildcard(addr, &requested_port)) {
822
+ return add_wildcard_addrs_to_server(s, port_index, requested_port,
823
+ out_port);
824
+ }
600
825
  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
601
826
  addr = &addr6_v4mapped;
602
827
  }
603
-
604
- /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
605
- if (grpc_sockaddr_is_wildcard(addr, &port)) {
606
- grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
607
-
608
- /* Try listening on IPv6 first. */
609
- addr = &wild6;
610
- errs[0] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
611
- if (errs[0] == GRPC_ERROR_NONE) {
612
- errs[0] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
613
- if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
614
- goto done;
615
- }
616
- if (sp != NULL) {
617
- ++fd_index;
618
- }
619
- /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
620
- if (port == 0 && sp != NULL) {
621
- grpc_sockaddr_set_port(&wild4, sp->port);
622
- }
623
- }
624
- addr = &wild4;
625
- }
626
-
627
- errs[1] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
628
- if (errs[1] == GRPC_ERROR_NONE) {
629
- if (dsmode == GRPC_DSMODE_IPV4 &&
630
- grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
631
- addr = &addr4_copy;
632
- }
633
- sp2 = sp;
634
- errs[1] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
635
- if (sp2 != NULL && sp != NULL) {
636
- sp2->sibling = sp;
637
- sp->is_sibling = 1;
638
- }
639
- }
640
-
641
- done:
642
- gpr_free(allocated_addr);
643
- if (sp != NULL) {
828
+ if ((err = add_addr_to_server(s, addr, port_index, 0, &dsmode, &sp)) ==
829
+ GRPC_ERROR_NONE) {
644
830
  *out_port = sp->port;
645
- GRPC_ERROR_UNREF(errs[0]);
646
- GRPC_ERROR_UNREF(errs[1]);
647
- return GRPC_ERROR_NONE;
648
- } else {
649
- *out_port = -1;
650
- char *addr_str = grpc_sockaddr_to_uri(addr);
651
- grpc_error *err = grpc_error_set_str(
652
- GRPC_ERROR_CREATE_REFERENCING("Failed to add port to server", errs,
653
- GPR_ARRAY_SIZE(errs)),
654
- GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
655
- GRPC_ERROR_UNREF(errs[0]);
656
- GRPC_ERROR_UNREF(errs[1]);
657
- gpr_free(addr_str);
658
- return err;
659
831
  }
832
+ return err;
660
833
  }
661
834
 
662
835
  /* Return listener at port_index or NULL. Should only be called with s->mu
@@ -769,11 +942,13 @@ void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
769
942
  void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx,
770
943
  grpc_tcp_server *s) {
771
944
  gpr_mu_lock(&s->mu);
945
+ s->shutdown_listeners = true;
772
946
  /* shutdown all fd's */
773
947
  if (s->active_ports) {
774
948
  grpc_tcp_listener *sp;
775
949
  for (sp = s->head; sp; sp = sp->next) {
776
- grpc_fd_shutdown(exec_ctx, sp->emfd);
950
+ grpc_fd_shutdown(exec_ctx, sp->emfd,
951
+ GRPC_ERROR_CREATE("Server shutdown"));
777
952
  }
778
953
  }
779
954
  gpr_mu_unlock(&s->mu);