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
@@ -38,16 +38,16 @@
38
38
  #include "src/core/lib/transport/metadata.h"
39
39
 
40
40
  /** Return compression algorithm based metadata value */
41
- grpc_mdstr *grpc_compression_algorithm_mdstr(
41
+ grpc_slice grpc_compression_algorithm_slice(
42
42
  grpc_compression_algorithm algorithm);
43
43
 
44
44
  /** Return compression algorithm based metadata element (grpc-encoding: xxx) */
45
- grpc_mdelem *grpc_compression_encoding_mdelem(
45
+ grpc_mdelem grpc_compression_encoding_mdelem(
46
46
  grpc_compression_algorithm algorithm);
47
47
 
48
48
  /** Find compression algorithm based on passed in mdstr - returns
49
49
  * GRPC_COMPRESS_ALGORITHM_COUNT on failure */
50
- grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
51
- grpc_mdstr *str);
50
+ grpc_compression_algorithm grpc_compression_algorithm_from_slice(
51
+ grpc_slice str);
52
52
 
53
53
  #endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */
@@ -41,30 +41,24 @@
41
41
  #include "src/core/lib/surface/api_trace.h"
42
42
  #include "src/core/lib/transport/static_metadata.h"
43
43
 
44
- int grpc_compression_algorithm_parse(const char *name, size_t name_length,
44
+ int grpc_compression_algorithm_parse(grpc_slice name,
45
45
  grpc_compression_algorithm *algorithm) {
46
46
  /* we use strncmp not only because it's safer (even though in this case it
47
47
  * doesn't matter, given that we are comparing against string literals, but
48
48
  * because this way we needn't have "name" nil-terminated (useful for slice
49
49
  * data, for example) */
50
- GRPC_API_TRACE(
51
- "grpc_compression_algorithm_parse("
52
- "name=%*.*s, name_length=%lu, algorithm=%p)",
53
- 5, ((int)name_length, (int)name_length, name, (unsigned long)name_length,
54
- algorithm));
55
- if (name_length == 0) {
56
- return 0;
57
- }
58
- if (strncmp(name, "identity", name_length) == 0) {
50
+ if (grpc_slice_eq(name, GRPC_MDSTR_IDENTITY)) {
59
51
  *algorithm = GRPC_COMPRESS_NONE;
60
- } else if (strncmp(name, "gzip", name_length) == 0) {
52
+ return 1;
53
+ } else if (grpc_slice_eq(name, GRPC_MDSTR_GZIP)) {
61
54
  *algorithm = GRPC_COMPRESS_GZIP;
62
- } else if (strncmp(name, "deflate", name_length) == 0) {
55
+ return 1;
56
+ } else if (grpc_slice_eq(name, GRPC_MDSTR_DEFLATE)) {
63
57
  *algorithm = GRPC_COMPRESS_DEFLATE;
58
+ return 1;
64
59
  } else {
65
60
  return 0;
66
61
  }
67
- return 1;
68
62
  }
69
63
 
70
64
  int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
@@ -87,15 +81,15 @@ int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm,
87
81
  return 0;
88
82
  }
89
83
 
90
- grpc_compression_algorithm grpc_compression_algorithm_from_mdstr(
91
- grpc_mdstr *str) {
92
- if (str == GRPC_MDSTR_IDENTITY) return GRPC_COMPRESS_NONE;
93
- if (str == GRPC_MDSTR_DEFLATE) return GRPC_COMPRESS_DEFLATE;
94
- if (str == GRPC_MDSTR_GZIP) return GRPC_COMPRESS_GZIP;
84
+ grpc_compression_algorithm grpc_compression_algorithm_from_slice(
85
+ grpc_slice str) {
86
+ if (grpc_slice_eq(str, GRPC_MDSTR_IDENTITY)) return GRPC_COMPRESS_NONE;
87
+ if (grpc_slice_eq(str, GRPC_MDSTR_DEFLATE)) return GRPC_COMPRESS_DEFLATE;
88
+ if (grpc_slice_eq(str, GRPC_MDSTR_GZIP)) return GRPC_COMPRESS_GZIP;
95
89
  return GRPC_COMPRESS_ALGORITHMS_COUNT;
96
90
  }
97
91
 
98
- grpc_mdstr *grpc_compression_algorithm_mdstr(
92
+ grpc_slice grpc_compression_algorithm_slice(
99
93
  grpc_compression_algorithm algorithm) {
100
94
  switch (algorithm) {
101
95
  case GRPC_COMPRESS_NONE:
@@ -105,12 +99,12 @@ grpc_mdstr *grpc_compression_algorithm_mdstr(
105
99
  case GRPC_COMPRESS_GZIP:
106
100
  return GRPC_MDSTR_GZIP;
107
101
  case GRPC_COMPRESS_ALGORITHMS_COUNT:
108
- return NULL;
102
+ return grpc_empty_slice();
109
103
  }
110
- return NULL;
104
+ return grpc_empty_slice();
111
105
  }
112
106
 
113
- grpc_mdelem *grpc_compression_encoding_mdelem(
107
+ grpc_mdelem grpc_compression_encoding_mdelem(
114
108
  grpc_compression_algorithm algorithm) {
115
109
  switch (algorithm) {
116
110
  case GRPC_COMPRESS_NONE:
@@ -122,7 +116,7 @@ grpc_mdelem *grpc_compression_encoding_mdelem(
122
116
  default:
123
117
  break;
124
118
  }
125
- return NULL;
119
+ return GRPC_MDNULL;
126
120
  }
127
121
 
128
122
  void grpc_compression_options_init(grpc_compression_options *opts) {
@@ -93,8 +93,9 @@ void grpc_httpcli_context_init(grpc_httpcli_context *context) {
93
93
  context->pollset_set = grpc_pollset_set_create();
94
94
  }
95
95
 
96
- void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
97
- grpc_pollset_set_destroy(context->pollset_set);
96
+ void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx,
97
+ grpc_httpcli_context *context) {
98
+ grpc_pollset_set_destroy(exec_ctx, context->pollset_set);
98
99
  }
99
100
 
100
101
  static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
@@ -83,7 +83,8 @@ typedef struct grpc_httpcli_request {
83
83
  typedef struct grpc_http_response grpc_httpcli_response;
84
84
 
85
85
  void grpc_httpcli_context_init(grpc_httpcli_context *context);
86
- void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
86
+ void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx,
87
+ grpc_httpcli_context *context);
87
88
 
88
89
  /* Asynchronously perform a HTTP GET.
89
90
  'context' specifies the http context under which to do the get
@@ -118,8 +118,7 @@ static grpc_security_status httpcli_ssl_channel_security_connector_create(
118
118
  return GRPC_SECURITY_ERROR;
119
119
  }
120
120
 
121
- c = gpr_malloc(sizeof(grpc_httpcli_ssl_channel_security_connector));
122
- memset(c, 0, sizeof(grpc_httpcli_ssl_channel_security_connector));
121
+ c = gpr_zalloc(sizeof(grpc_httpcli_ssl_channel_security_connector));
123
122
 
124
123
  gpr_ref_init(&c->base.base.refcount, 1);
125
124
  c->base.base.vtable = &httpcli_ssl_vtable;
@@ -156,7 +155,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
156
155
  if (error != GRPC_ERROR_NONE) {
157
156
  const char *msg = grpc_error_string(error);
158
157
  gpr_log(GPR_ERROR, "Secure transport setup failed: %s", msg);
159
- grpc_error_free_string(msg);
158
+
160
159
  c->func(exec_ctx, c->arg, NULL);
161
160
  } else {
162
161
  grpc_channel_args_destroy(exec_ctx, args->args);
@@ -284,9 +284,9 @@ static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte,
284
284
  case GRPC_HTTP_HEADERS:
285
285
  if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) {
286
286
  if (grpc_http1_trace)
287
- gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded",
287
+ gpr_log(GPR_ERROR, "HTTP header max line length (%d) exceeded",
288
288
  GRPC_HTTP_PARSER_MAX_HEADER_LENGTH);
289
- return GRPC_ERROR_NONE;
289
+ return GRPC_ERROR_CREATE("HTTP header max line length exceeded");
290
290
  }
291
291
  parser->cur_line[parser->cur_line_length] = byte;
292
292
  parser->cur_line_length++;
@@ -34,6 +34,7 @@
34
34
  #include "src/core/lib/iomgr/closure.h"
35
35
 
36
36
  #include <grpc/support/alloc.h>
37
+ #include <grpc/support/log.h>
37
38
 
38
39
  #include "src/core/lib/profiling/timers.h"
39
40
 
@@ -50,20 +51,22 @@ void grpc_closure_list_init(grpc_closure_list *closure_list) {
50
51
  closure_list->head = closure_list->tail = NULL;
51
52
  }
52
53
 
53
- void grpc_closure_list_append(grpc_closure_list *closure_list,
54
+ bool grpc_closure_list_append(grpc_closure_list *closure_list,
54
55
  grpc_closure *closure, grpc_error *error) {
55
56
  if (closure == NULL) {
56
57
  GRPC_ERROR_UNREF(error);
57
- return;
58
+ return false;
58
59
  }
59
60
  closure->error_data.error = error;
60
61
  closure->next_data.next = NULL;
61
- if (closure_list->head == NULL) {
62
+ bool was_empty = (closure_list->head == NULL);
63
+ if (was_empty) {
62
64
  closure_list->head = closure;
63
65
  } else {
64
66
  closure_list->tail->next_data.next = closure;
65
67
  }
66
68
  closure_list->tail = closure;
69
+ return was_empty;
67
70
  }
68
71
 
69
72
  void grpc_closure_list_fail_all(grpc_closure_list *list,
@@ -66,6 +66,7 @@ typedef struct grpc_closure_scheduler_vtable {
66
66
  grpc_error *error);
67
67
  void (*sched)(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
68
68
  grpc_error *error);
69
+ const char *name;
69
70
  } grpc_closure_scheduler_vtable;
70
71
 
71
72
  /** Abstract type that can schedule closures for execution */
@@ -115,8 +116,9 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg,
115
116
  void grpc_closure_list_init(grpc_closure_list *list);
116
117
 
117
118
  /** add \a closure to the end of \a list
118
- and set \a closure's result to \a error */
119
- void grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure,
119
+ and set \a closure's result to \a error
120
+ Returns true if \a list becomes non-empty */
121
+ bool grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure,
120
122
  grpc_error *error);
121
123
 
122
124
  /** force all success bits in \a list to false */
@@ -72,6 +72,7 @@ struct grpc_combiner {
72
72
  bool final_list_covered_by_poller;
73
73
  grpc_closure_list final_list;
74
74
  grpc_closure offload;
75
+ gpr_refcount refs;
75
76
  };
76
77
 
77
78
  static void combiner_exec_uncovered(grpc_exec_ctx *exec_ctx,
@@ -86,13 +87,17 @@ static void combiner_finally_exec_covered(grpc_exec_ctx *exec_ctx,
86
87
  grpc_error *error);
87
88
 
88
89
  static const grpc_closure_scheduler_vtable scheduler_uncovered = {
89
- combiner_exec_uncovered, combiner_exec_uncovered};
90
+ combiner_exec_uncovered, combiner_exec_uncovered,
91
+ "combiner:immediately:uncovered"};
90
92
  static const grpc_closure_scheduler_vtable scheduler_covered = {
91
- combiner_exec_covered, combiner_exec_covered};
93
+ combiner_exec_covered, combiner_exec_covered,
94
+ "combiner:immediately:covered"};
92
95
  static const grpc_closure_scheduler_vtable finally_scheduler_uncovered = {
93
- combiner_finally_exec_uncovered, combiner_finally_exec_uncovered};
96
+ combiner_finally_exec_uncovered, combiner_finally_exec_uncovered,
97
+ "combiner:finally:uncovered"};
94
98
  static const grpc_closure_scheduler_vtable finally_scheduler_covered = {
95
- combiner_finally_exec_covered, combiner_finally_exec_covered};
99
+ combiner_finally_exec_covered, combiner_finally_exec_covered,
100
+ "combiner:finally:covered"};
96
101
 
97
102
  static void offload(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
98
103
 
@@ -122,6 +127,7 @@ static bool is_covered_by_poller(grpc_combiner *lock) {
122
127
 
123
128
  grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) {
124
129
  grpc_combiner *lock = gpr_malloc(sizeof(*lock));
130
+ gpr_ref_init(&lock->refs, 1);
125
131
  lock->next_combiner_on_this_exec_ctx = NULL;
126
132
  lock->time_to_execute_final_list = false;
127
133
  lock->optional_workqueue = optional_workqueue;
@@ -148,7 +154,7 @@ static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
148
154
  gpr_free(lock);
149
155
  }
150
156
 
151
- void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
157
+ static void start_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
152
158
  gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_UNORPHANED);
153
159
  GRPC_COMBINER_TRACE(gpr_log(
154
160
  GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state));
@@ -157,6 +163,30 @@ void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
157
163
  }
158
164
  }
159
165
 
166
+ #ifdef GRPC_COMBINER_REFCOUNT_DEBUG
167
+ #define GRPC_COMBINER_DEBUG_SPAM(op, delta) \
168
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, \
169
+ "combiner[%p] %s %" PRIdPTR " --> %" PRIdPTR " %s", lock, (op), \
170
+ gpr_atm_no_barrier_load(&lock->refs.count), \
171
+ gpr_atm_no_barrier_load(&lock->refs.count) + (delta), reason);
172
+ #else
173
+ #define GRPC_COMBINER_DEBUG_SPAM(op, delta)
174
+ #endif
175
+
176
+ void grpc_combiner_unref(grpc_exec_ctx *exec_ctx,
177
+ grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) {
178
+ GRPC_COMBINER_DEBUG_SPAM("UNREF", -1);
179
+ if (gpr_unref(&lock->refs)) {
180
+ start_destroy(exec_ctx, lock);
181
+ }
182
+ }
183
+
184
+ grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) {
185
+ GRPC_COMBINER_DEBUG_SPAM(" REF", 1);
186
+ gpr_ref(&lock->refs);
187
+ return lock;
188
+ }
189
+
160
190
  static void push_last_on_exec_ctx(grpc_exec_ctx *exec_ctx,
161
191
  grpc_combiner *lock) {
162
192
  lock->next_combiner_on_this_exec_ctx = NULL;
@@ -48,8 +48,27 @@
48
48
  // Initialize the lock, with an optional workqueue to shift load to when
49
49
  // necessary
50
50
  grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue);
51
- // Destroy the lock
52
- void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock);
51
+
52
+ //#define GRPC_COMBINER_REFCOUNT_DEBUG
53
+ #ifdef GRPC_COMBINER_REFCOUNT_DEBUG
54
+ #define GRPC_COMBINER_DEBUG_ARGS \
55
+ , const char *file, int line, const char *reason
56
+ #define GRPC_COMBINER_REF(combiner, reason) \
57
+ grpc_combiner_ref((combiner), __FILE__, __LINE__, (reason))
58
+ #define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \
59
+ grpc_combiner_unref((exec_ctx), (combiner), __FILE__, __LINE__, (reason))
60
+ #else
61
+ #define GRPC_COMBINER_DEBUG_ARGS
62
+ #define GRPC_COMBINER_REF(combiner, reason) grpc_combiner_ref((combiner))
63
+ #define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \
64
+ grpc_combiner_unref((exec_ctx), (combiner))
65
+ #endif
66
+
67
+ // Ref/unref the lock, for when we're sharing the lock ownership
68
+ // Prefer to use the macros above
69
+ grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS);
70
+ void grpc_combiner_unref(grpc_exec_ctx *exec_ctx,
71
+ grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS);
53
72
  // Fetch a scheduler to schedule closures against
54
73
  grpc_closure_scheduler *grpc_combiner_scheduler(grpc_combiner *lock,
55
74
  bool covered_by_poller);
@@ -54,8 +54,9 @@ void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx* exec_ctx,
54
54
  ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set);
55
55
  }
56
56
 
57
- void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
58
- ep->vtable->shutdown(exec_ctx, ep);
57
+ void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
58
+ grpc_error* why) {
59
+ ep->vtable->shutdown(exec_ctx, ep, why);
59
60
  }
60
61
 
61
62
  void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
@@ -57,7 +57,7 @@ struct grpc_endpoint_vtable {
57
57
  grpc_pollset *pollset);
58
58
  void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
59
59
  grpc_pollset_set *pollset);
60
- void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
60
+ void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why);
61
61
  void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
62
62
  grpc_resource_user *(*get_resource_user)(grpc_endpoint *ep);
63
63
  char *(*get_peer)(grpc_endpoint *ep);
@@ -96,7 +96,8 @@ void grpc_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
96
96
 
97
97
  /* Causes any pending and future read/write callbacks to run immediately with
98
98
  success==0 */
99
- void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
99
+ void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
100
+ grpc_error *why);
100
101
  void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
101
102
 
102
103
  /* Add an endpoint to a pollset, so that when the pollset is polled, events from
@@ -33,13 +33,10 @@
33
33
 
34
34
  #include "src/core/lib/iomgr/error.h"
35
35
 
36
- #include <inttypes.h>
37
- #include <stdbool.h>
38
36
  #include <string.h>
39
37
 
40
38
  #include <grpc/status.h>
41
39
  #include <grpc/support/alloc.h>
42
- #include <grpc/support/avl.h>
43
40
  #include <grpc/support/log.h>
44
41
  #include <grpc/support/string_util.h>
45
42
  #include <grpc/support/useful.h>
@@ -48,6 +45,7 @@
48
45
  #include <grpc/support/log_windows.h>
49
46
  #endif
50
47
 
48
+ #include "src/core/lib/iomgr/error_internal.h"
51
49
  #include "src/core/lib/profiling/timers.h"
52
50
 
53
51
  static void destroy_integer(void *key) {}
@@ -128,6 +126,10 @@ static const char *error_int_name(grpc_error_ints key) {
128
126
 
129
127
  static const char *error_str_name(grpc_error_strs key) {
130
128
  switch (key) {
129
+ case GRPC_ERROR_STR_KEY:
130
+ return "key";
131
+ case GRPC_ERROR_STR_VALUE:
132
+ return "value";
131
133
  case GRPC_ERROR_STR_DESCRIPTION:
132
134
  return "description";
133
135
  case GRPC_ERROR_STR_OS_ERROR:
@@ -160,16 +162,7 @@ static const char *error_time_name(grpc_error_times key) {
160
162
  GPR_UNREACHABLE_CODE(return "unknown");
161
163
  }
162
164
 
163
- struct grpc_error {
164
- gpr_refcount refs;
165
- gpr_avl ints;
166
- gpr_avl strs;
167
- gpr_avl times;
168
- gpr_avl errs;
169
- uintptr_t next_err;
170
- };
171
-
172
- static bool is_special(grpc_error *err) {
165
+ bool grpc_error_is_special(grpc_error *err) {
173
166
  return err == GRPC_ERROR_NONE || err == GRPC_ERROR_OOM ||
174
167
  err == GRPC_ERROR_CANCELLED;
175
168
  }
@@ -177,7 +170,7 @@ static bool is_special(grpc_error *err) {
177
170
  #ifdef GRPC_ERROR_REFCOUNT_DEBUG
178
171
  grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line,
179
172
  const char *func) {
180
- if (is_special(err)) return err;
173
+ if (grpc_error_is_special(err)) return err;
181
174
  gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err,
182
175
  err->refs.count, err->refs.count + 1, file, line, func);
183
176
  gpr_ref(&err->refs);
@@ -185,25 +178,26 @@ grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line,
185
178
  }
186
179
  #else
187
180
  grpc_error *grpc_error_ref(grpc_error *err) {
188
- if (is_special(err)) return err;
181
+ if (grpc_error_is_special(err)) return err;
189
182
  gpr_ref(&err->refs);
190
183
  return err;
191
184
  }
192
185
  #endif
193
186
 
194
187
  static void error_destroy(grpc_error *err) {
195
- GPR_ASSERT(!is_special(err));
188
+ GPR_ASSERT(!grpc_error_is_special(err));
196
189
  gpr_avl_unref(err->ints);
197
190
  gpr_avl_unref(err->strs);
198
191
  gpr_avl_unref(err->errs);
199
192
  gpr_avl_unref(err->times);
193
+ gpr_free((void *)gpr_atm_acq_load(&err->error_string));
200
194
  gpr_free(err);
201
195
  }
202
196
 
203
197
  #ifdef GRPC_ERROR_REFCOUNT_DEBUG
204
198
  void grpc_error_unref(grpc_error *err, const char *file, int line,
205
199
  const char *func) {
206
- if (is_special(err)) return;
200
+ if (grpc_error_is_special(err)) return;
207
201
  gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err,
208
202
  err->refs.count, err->refs.count - 1, file, line, func);
209
203
  if (gpr_unref(&err->refs)) {
@@ -212,7 +206,7 @@ void grpc_error_unref(grpc_error *err, const char *file, int line,
212
206
  }
213
207
  #else
214
208
  void grpc_error_unref(grpc_error *err) {
215
- if (is_special(err)) return;
209
+ if (grpc_error_is_special(err)) return;
216
210
  if (gpr_unref(&err->refs)) {
217
211
  error_destroy(err);
218
212
  }
@@ -247,6 +241,7 @@ grpc_error *grpc_error_create(const char *file, int line, const char *desc,
247
241
  err->times = gpr_avl_add(gpr_avl_create(&avl_vtable_times),
248
242
  (void *)(uintptr_t)GRPC_ERROR_TIME_CREATED,
249
243
  box_time(gpr_now(GPR_CLOCK_REALTIME)));
244
+ gpr_atm_no_barrier_store(&err->error_string, 0);
250
245
  gpr_ref_init(&err->refs, 1);
251
246
  GPR_TIMER_END("grpc_error_create", 0);
252
247
  return err;
@@ -255,9 +250,10 @@ grpc_error *grpc_error_create(const char *file, int line, const char *desc,
255
250
  static grpc_error *copy_error_and_unref(grpc_error *in) {
256
251
  GPR_TIMER_BEGIN("copy_error_and_unref", 0);
257
252
  grpc_error *out;
258
- if (is_special(in)) {
253
+ if (grpc_error_is_special(in)) {
259
254
  if (in == GRPC_ERROR_NONE)
260
- out = GRPC_ERROR_CREATE("no error");
255
+ out = grpc_error_set_int(GRPC_ERROR_CREATE("no error"),
256
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK);
261
257
  else if (in == GRPC_ERROR_OOM)
262
258
  out = GRPC_ERROR_CREATE("oom");
263
259
  else if (in == GRPC_ERROR_CANCELLED)
@@ -275,6 +271,7 @@ static grpc_error *copy_error_and_unref(grpc_error *in) {
275
271
  out->strs = gpr_avl_ref(in->strs);
276
272
  out->errs = gpr_avl_ref(in->errs);
277
273
  out->times = gpr_avl_ref(in->times);
274
+ gpr_atm_no_barrier_store(&out->error_string, 0);
278
275
  out->next_err = in->next_err;
279
276
  gpr_ref_init(&out->refs, 1);
280
277
  GRPC_ERROR_UNREF(in);
@@ -292,14 +289,29 @@ grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which,
292
289
  return new;
293
290
  }
294
291
 
292
+ typedef struct {
293
+ grpc_error *error;
294
+ grpc_status_code code;
295
+ const char *msg;
296
+ } special_error_status_map;
297
+ static special_error_status_map error_status_map[] = {
298
+ {GRPC_ERROR_NONE, GRPC_STATUS_OK, NULL},
299
+ {GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "Cancelled"},
300
+ {GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"},
301
+ };
302
+
295
303
  bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) {
296
304
  GPR_TIMER_BEGIN("grpc_error_get_int", 0);
297
305
  void *pp;
298
- if (is_special(err)) {
299
- if (err == GRPC_ERROR_CANCELLED && which == GRPC_ERROR_INT_GRPC_STATUS) {
300
- *p = GRPC_STATUS_CANCELLED;
301
- GPR_TIMER_END("grpc_error_get_int", 0);
302
- return true;
306
+ if (grpc_error_is_special(err)) {
307
+ if (which == GRPC_ERROR_INT_GRPC_STATUS) {
308
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
309
+ if (error_status_map[i].error == err) {
310
+ if (p != NULL) *p = error_status_map[i].code;
311
+ GPR_TIMER_END("grpc_error_get_int", 0);
312
+ return true;
313
+ }
314
+ }
303
315
  }
304
316
  GPR_TIMER_END("grpc_error_get_int", 0);
305
317
  return false;
@@ -324,66 +336,17 @@ grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
324
336
  }
325
337
 
326
338
  const char *grpc_error_get_str(grpc_error *err, grpc_error_strs which) {
327
- if (is_special(err)) return NULL;
328
- return gpr_avl_get(err->strs, (void *)(uintptr_t)which);
329
- }
330
-
331
- typedef struct {
332
- grpc_error *error;
333
- grpc_status_code code;
334
- const char *msg;
335
- } special_error_status_map;
336
- static special_error_status_map error_status_map[] = {
337
- {GRPC_ERROR_NONE, GRPC_STATUS_OK, ""},
338
- {GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "RPC cancelled"},
339
- {GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"},
340
- };
341
-
342
- static grpc_error *recursively_find_error_with_status(grpc_error *error,
343
- intptr_t *status) {
344
- // If the error itself has a status code, return it.
345
- if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, status)) {
346
- return error;
347
- }
348
- // Otherwise, search through its children.
349
- intptr_t key = 0;
350
- while (true) {
351
- grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++);
352
- if (child_error == NULL) break;
353
- grpc_error *result =
354
- recursively_find_error_with_status(child_error, status);
355
- if (result != NULL) return result;
356
- }
357
- return NULL;
358
- }
359
-
360
- void grpc_error_get_status(grpc_error *error, grpc_status_code *code,
361
- const char **msg) {
362
- // Handle special errors via the static map.
363
- for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); ++i) {
364
- if (error == error_status_map[i].error) {
365
- *code = error_status_map[i].code;
366
- *msg = error_status_map[i].msg;
367
- return;
339
+ if (grpc_error_is_special(err)) {
340
+ if (which == GRPC_ERROR_STR_GRPC_MESSAGE) {
341
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
342
+ if (error_status_map[i].error == err) {
343
+ return error_status_map[i].msg;
344
+ }
345
+ }
368
346
  }
347
+ return NULL;
369
348
  }
370
- // Populate code.
371
- // Start with the parent error and recurse through the tree of children
372
- // until we find the first one that has a status code.
373
- intptr_t status = GRPC_STATUS_UNKNOWN; // Default in case we don't find one.
374
- grpc_error *found_error = recursively_find_error_with_status(error, &status);
375
- *code = (grpc_status_code)status;
376
- // Now populate msg.
377
- // If we found an error with a status code above, use that; otherwise,
378
- // fall back to using the parent error.
379
- if (found_error == NULL) found_error = error;
380
- // If the error has a status message, use it. Otherwise, fall back to
381
- // the error description.
382
- *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE);
383
- if (*msg == NULL) {
384
- *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION);
385
- if (*msg == NULL) *msg = "uknown error"; // Just in case.
386
- }
349
+ return gpr_avl_get(err->strs, (void *)(uintptr_t)which);
387
350
  }
388
351
 
389
352
  grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) {
@@ -535,7 +498,6 @@ static void add_errs(gpr_avl_node *n, char **s, size_t *sz, size_t *cap,
535
498
  *first = false;
536
499
  const char *e = grpc_error_string(n->value);
537
500
  append_str(e, s, sz, cap);
538
- grpc_error_free_string(e);
539
501
  add_errs(n->right, s, sz, cap, first);
540
502
  }
541
503
 
@@ -557,7 +519,7 @@ static int cmp_kvs(const void *a, const void *b) {
557
519
  return strcmp(ka->key, kb->key);
558
520
  }
559
521
 
560
- static const char *finish_kvs(kv_pairs *kvs) {
522
+ static char *finish_kvs(kv_pairs *kvs) {
561
523
  char *s = NULL;
562
524
  size_t sz = 0;
563
525
  size_t cap = 0;
@@ -578,19 +540,18 @@ static const char *finish_kvs(kv_pairs *kvs) {
578
540
  return s;
579
541
  }
580
542
 
581
- void grpc_error_free_string(const char *str) {
582
- if (str == no_error_string) return;
583
- if (str == oom_error_string) return;
584
- if (str == cancelled_error_string) return;
585
- gpr_free((char *)str);
586
- }
587
-
588
543
  const char *grpc_error_string(grpc_error *err) {
589
544
  GPR_TIMER_BEGIN("grpc_error_string", 0);
590
545
  if (err == GRPC_ERROR_NONE) return no_error_string;
591
546
  if (err == GRPC_ERROR_OOM) return oom_error_string;
592
547
  if (err == GRPC_ERROR_CANCELLED) return cancelled_error_string;
593
548
 
549
+ void *p = (void *)gpr_atm_acq_load(&err->error_string);
550
+ if (p != NULL) {
551
+ GPR_TIMER_END("grpc_error_string", 0);
552
+ return p;
553
+ }
554
+
594
555
  kv_pairs kvs;
595
556
  memset(&kvs, 0, sizeof(kvs));
596
557
 
@@ -603,7 +564,13 @@ const char *grpc_error_string(grpc_error *err) {
603
564
 
604
565
  qsort(kvs.kvs, kvs.num_kvs, sizeof(kv_pair), cmp_kvs);
605
566
 
606
- const char *out = finish_kvs(&kvs);
567
+ char *out = finish_kvs(&kvs);
568
+
569
+ if (!gpr_atm_rel_cas(&err->error_string, 0, (gpr_atm)out)) {
570
+ gpr_free(out);
571
+ out = (char *)gpr_atm_no_barrier_load(&err->error_string);
572
+ }
573
+
607
574
  GPR_TIMER_END("grpc_error_string", 0);
608
575
  return out;
609
576
  }
@@ -638,7 +605,6 @@ bool grpc_log_if_error(const char *what, grpc_error *error, const char *file,
638
605
  if (error == GRPC_ERROR_NONE) return true;
639
606
  const char *msg = grpc_error_string(error);
640
607
  gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what, msg);
641
- grpc_error_free_string(msg);
642
608
  GRPC_ERROR_UNREF(error);
643
609
  return false;
644
610
  }