Merge github.com:grpc/grpc into cq-drop

pull/11317/head
Craig Tiller 8 years ago
commit 39a7327c5f
  1. 2
      .github/ISSUE_TEMPLATE.md
  2. 71
      .pylintrc
  3. 6
      BUILD
  4. 384
      CMakeLists.txt
  5. 20
      LICENSE
  6. 825
      Makefile
  7. 59
      binding.gyp
  8. 11
      build.yaml
  9. 25
      config.m4
  10. 153
      config.w32
  11. 16
      doc/PROTOCOL-HTTP2.md
  12. 19
      doc/environment_variables.md
  13. 3
      gRPC-Core.podspec
  14. 31
      grpc.gemspec
  15. 21
      include/grpc++/alarm.h
  16. 90
      include/grpc++/impl/codegen/async_unary_call.h
  17. 22
      include/grpc++/impl/codegen/call.h
  18. 2
      package.json
  19. 31
      package.xml
  20. 6
      setup.py
  21. 536
      src/boringssl/err_data.c
  22. 40
      src/compiler/php_generator.cc
  23. 14
      src/compiler/php_generator_helpers.h
  24. 667
      src/core/ext/filters/client_channel/client_channel.c
  25. 3
      src/core/ext/filters/client_channel/client_channel_plugin.c
  26. 17
      src/core/ext/filters/client_channel/lb_policy.c
  27. 7
      src/core/ext/filters/client_channel/lb_policy.h
  28. 3
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
  29. 45
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c
  30. 38
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c
  31. 35
      src/core/ext/filters/client_channel/resolver.c
  32. 14
      src/core/ext/filters/client_channel/resolver.h
  33. 2
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
  34. 2
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
  35. 19
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c
  36. 4
      src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c
  37. 24
      src/core/ext/filters/client_channel/subchannel.c
  38. 2
      src/core/ext/filters/client_channel/subchannel.h
  39. 35
      src/core/ext/filters/http/message_compress/message_compress_filter.c
  40. 3
      src/core/ext/transport/chttp2/transport/chttp2_plugin.c
  41. 69
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  42. 4
      src/core/ext/transport/chttp2/transport/chttp2_transport.h
  43. 2
      src/core/ext/transport/chttp2/transport/frame_rst_stream.c
  44. 14
      src/core/ext/transport/chttp2/transport/hpack_encoder.c
  45. 2
      src/core/ext/transport/chttp2/transport/hpack_encoder.h
  46. 6
      src/core/ext/transport/chttp2/transport/internal.h
  47. 12
      src/core/ext/transport/chttp2/transport/parsing.c
  48. 87
      src/core/ext/transport/chttp2/transport/writing.c
  49. 52
      src/core/ext/transport/cronet/transport/cronet_transport.c
  50. 2
      src/core/lib/channel/channel_stack.h
  51. 10
      src/core/lib/http/httpcli_security_connector.c
  52. 24
      src/core/lib/iomgr/closure.c
  53. 30
      src/core/lib/iomgr/closure.h
  54. 18
      src/core/lib/iomgr/combiner.c
  55. 3
      src/core/lib/iomgr/combiner.h
  56. 55
      src/core/lib/iomgr/error.c
  57. 20
      src/core/lib/iomgr/error.h
  58. 6
      src/core/lib/iomgr/ev_epoll1_linux.c
  59. 65
      src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c
  60. 28
      src/core/lib/iomgr/ev_epoll_thread_pool_linux.c
  61. 32
      src/core/lib/iomgr/ev_epollex_linux.c
  62. 62
      src/core/lib/iomgr/ev_epollsig_linux.c
  63. 35
      src/core/lib/iomgr/ev_poll_posix.c
  64. 4
      src/core/lib/iomgr/ev_posix.c
  65. 15
      src/core/lib/iomgr/exec_ctx.c
  66. 2
      src/core/lib/iomgr/executor.c
  67. 4
      src/core/lib/iomgr/pollset.h
  68. 6
      src/core/lib/iomgr/pollset_uv.c
  69. 4
      src/core/lib/iomgr/pollset_windows.c
  70. 19
      src/core/lib/iomgr/tcp_posix.c
  71. 21
      src/core/lib/iomgr/tcp_uv.c
  72. 21
      src/core/lib/iomgr/tcp_windows.c
  73. 27
      src/core/lib/security/context/security_context.c
  74. 6
      src/core/lib/security/context/security_context.h
  75. 22
      src/core/lib/security/transport/secure_endpoint.c
  76. 27
      src/core/lib/security/transport/security_connector.c
  77. 6
      src/core/lib/security/transport/security_connector.h
  78. 137
      src/core/lib/support/stack_lockfree.c
  79. 38
      src/core/lib/support/stack_lockfree.h
  80. 16
      src/core/lib/support/time_precise.c
  81. 55
      src/core/lib/surface/call.c
  82. 2
      src/core/lib/surface/call.h
  83. 2
      src/core/lib/surface/channel.c
  84. 2
      src/core/lib/surface/channel.h
  85. 46
      src/core/lib/surface/completion_queue.c
  86. 6
      src/core/lib/surface/completion_queue.h
  87. 13
      src/core/lib/surface/init.c
  88. 10
      src/core/lib/surface/init_secure.c
  89. 2
      src/core/lib/surface/server.c
  90. 136
      src/core/lib/transport/metadata.c
  91. 8
      src/core/lib/transport/metadata.h
  92. 39
      src/core/lib/transport/transport.c
  93. 22
      src/core/lib/transport/transport.h
  94. 54
      src/cpp/common/channel_filter.h
  95. 16
      src/csharp/Grpc.Core.Tests/ServerTest.cs
  96. 21
      src/csharp/Grpc.Core/Server.cs
  97. 260
      src/csharp/Grpc.IntegrationTesting/Control.cs
  98. 112
      src/csharp/Grpc.IntegrationTesting/CustomErrorDetailsTest.cs
  99. 1354
      src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
  100. 34
      src/csharp/Grpc.IntegrationTesting/Services.cs
  101. Some files were not shown because too many files have changed in this diff Show More

@ -6,7 +6,7 @@ Create new issues for bugs and feature requests. An issue needs to be actionable
- [grpc.io mailing list](https://groups.google.com/forum/#!forum/grpc-io) - [grpc.io mailing list](https://groups.google.com/forum/#!forum/grpc-io)
- [StackOverflow, with `grpc` tag](http://stackoverflow.com/questions/tagged/grpc) - [StackOverflow, with `grpc` tag](http://stackoverflow.com/questions/tagged/grpc)
*Please don't double post your questions in more locations, we are monitoring both channels and the time spent de-duplicating questions can is better spent answering more user questions.* *Please don't double post your questions in more locations; we are monitoring both channels, and the time spent de-duplicating questions is better spent answering more user questions.*
### What version of gRPC and what language are you using? ### What version of gRPC and what language are you using?

@ -1,15 +1,18 @@
[VARIABLES] [VARIABLES]
# TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection # TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection
# not include "unused_" and "ignored_" by default? # not include "unused_" and "ignored_" by default?
dummy-variables-rgx=^ignored_|^unused_ dummy-variables-rgx=^ignored_|^unused_
[DESIGN] [DESIGN]
# NOTE(nathaniel): Not particularly attached to this value; it just seems to # NOTE(nathaniel): Not particularly attached to this value; it just seems to
# be what works for us at the moment (excepting the dead-code-walking Beta # be what works for us at the moment (excepting the dead-code-walking Beta
# API). # API).
max-args=6 max-args=6
[MISCELLANEOUS] [MISCELLANEOUS]
# NOTE(nathaniel): We are big fans of "TODO(<issue link>): " and # NOTE(nathaniel): We are big fans of "TODO(<issue link>): " and
# "NOTE(<username or issue link>): ". We do not allow "TODO:", # "NOTE(<username or issue link>): ". We do not allow "TODO:",
# "TODO(<username>):", "FIXME:", or anything else. # "TODO(<username>):", "FIXME:", or anything else.
@ -17,24 +20,50 @@ notes=FIXME,XXX
[MESSAGES CONTROL] [MESSAGES CONTROL]
#TODO: Enable missing-docstring disable=
#TODO: Enable too-few-public-methods # TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279):
#TODO: Enable no-init # Enable cyclic-import after a 1.7-or-later pylint release that
#TODO: Enable duplicate-code # recognizes our disable=cyclic-import suppressions.
#TODO: Enable invalid-name cyclic-import,
#TODO: Enable locally-disabled # TODO(https://github.com/grpc/grpc/issues/8622): Enable this after the
#TODO: Enable protected-access # Beta API is removed.
#TODO: Enable no-name-in-module duplicate-code,
#TODO: Enable wrong-import-order # TODO(https://github.com/grpc/grpc/issues/261): Doesn't seem to
# TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279): # understand enum and concurrent.futures; look into this later with the
# enable cyclic-import after a 1.7-or-later pylint release that recognizes our # latest pylint version.
# disable=cyclic-import suppressions. import-error,
#TODO: Enable too-many-instance-attributes # TODO(https://github.com/grpc/grpc/issues/261): Enable this one.
#TODO: Enable too-many-lines # Should take a little configuration but not much.
#TODO: Enable redefined-variable-type invalid-name,
#TODO: Enable next-method-called # TODO(https://github.com/grpc/grpc/issues/261): This doesn't seem to
#TODO: Enable import-error # work for now? Try with a later pylint?
#TODO: Enable useless-else-on-loop locally-disabled,
#TODO: Enable too-many-nested-blocks # NOTE(nathaniel): We don't write doc strings for most private code
# elements.
disable=missing-docstring,too-few-public-methods,no-init,duplicate-code,invalid-name,locally-disabled,protected-access,no-name-in-module,wrong-import-order,cyclic-import,too-many-instance-attributes,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-nested-blocks missing-docstring,
# NOTE(nathaniel): Our completely abstract interface classes don't have
# constructors.
no-init,
# TODO(https://github.com/grpc/grpc/issues/261): Doesn't yet play
# nicely with some of our code being implemented in Cython. Maybe in a
# later version?
no-name-in-module,
# TODO(https://github.com/grpc/grpc/issues/261): Suppress these where
# the odd shape of the authentication portion of the API forces them on
# us and enable everywhere else.
protected-access,
# NOTE(nathaniel): Pylint and I will probably never agree on this.
too-few-public-methods,
# NOTE(nathaniel): Pylint and I wil probably never agree on this for
# private classes. For public classes maybe?
too-many-instance-attributes,
# NOTE(nathaniel): Some of our modules have a lot of lines... of
# specification and documentation. Maybe if this were
# lines-of-code-based we would use it.
too-many-lines,
# TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have
# this one if we extracted just a few more helper functions...
too-many-nested-blocks,
# NOTE(nathaniel): I have disputed the premise of this inspection from
# the beginning and will continue to do so until it goes away for good.
useless-else-on-loop,

@ -335,7 +335,6 @@ grpc_cc_library(
"src/core/lib/support/log_windows.c", "src/core/lib/support/log_windows.c",
"src/core/lib/support/mpscq.c", "src/core/lib/support/mpscq.c",
"src/core/lib/support/murmur_hash.c", "src/core/lib/support/murmur_hash.c",
"src/core/lib/support/stack_lockfree.c",
"src/core/lib/support/string.c", "src/core/lib/support/string.c",
"src/core/lib/support/string_posix.c", "src/core/lib/support/string_posix.c",
"src/core/lib/support/string_util_windows.c", "src/core/lib/support/string_util_windows.c",
@ -371,7 +370,6 @@ grpc_cc_library(
"src/core/lib/support/mpscq.h", "src/core/lib/support/mpscq.h",
"src/core/lib/support/murmur_hash.h", "src/core/lib/support/murmur_hash.h",
"src/core/lib/support/spinlock.h", "src/core/lib/support/spinlock.h",
"src/core/lib/support/stack_lockfree.h",
"src/core/lib/support/string.h", "src/core/lib/support/string.h",
"src/core/lib/support/string_windows.h", "src/core/lib/support/string_windows.h",
"src/core/lib/support/thd_internal.h", "src/core/lib/support/thd_internal.h",
@ -930,8 +928,8 @@ grpc_cc_library(
deps = [ deps = [
"grpc_base", "grpc_base",
"grpc_client_channel", "grpc_client_channel",
"grpc_secure",
"grpc_resolver_fake", "grpc_resolver_fake",
"grpc_secure",
], ],
) )
@ -1025,8 +1023,8 @@ grpc_cc_library(
name = "grpc_resolver_fake", name = "grpc_resolver_fake",
srcs = ["src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c"], srcs = ["src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c"],
hdrs = ["src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"], hdrs = ["src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"],
visibility = ["//test:__subpackages__"],
language = "c", language = "c",
visibility = ["//test:__subpackages__"],
deps = [ deps = [
"grpc_base", "grpc_base",
"grpc_client_channel", "grpc_client_channel",

File diff suppressed because it is too large Load Diff

@ -1,13 +1,14 @@
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004
https://www.apache.org/licenses/ http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions. 1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, "License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by "Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License. the copyright owner that is granting the License.
@ -86,6 +87,7 @@
granted to You under this License for that Work shall terminate granted to You under this License for that Work shall terminate
as of the date such litigation is filed. as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You modifications, and in Source or Object form, provided that You
meet the following conditions: meet the following conditions:
@ -103,6 +105,7 @@
the Derivative Works; and the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its (d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one pertain to any part of the Derivative Works, in at least one
@ -120,7 +123,9 @@
You may add Your own copyright statement to Your modifications and You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use, for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License. the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, 5. Submission of Contributions. Unless You explicitly state otherwise,
@ -171,7 +176,18 @@
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
Copyright 2015-2017 gRPC authors. APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

File diff suppressed because it is too large Load Diff

@ -115,6 +115,15 @@
] ]
}, { }, {
'conditions': [ 'conditions': [
["target_arch=='ia32'", {
"include_dirs": [ "<(node_root_dir)/deps/openssl/config/piii" ]
}],
["target_arch=='x64'", {
"include_dirs": [ "<(node_root_dir)/deps/openssl/config/k8" ]
}],
["target_arch=='arm'", {
"include_dirs": [ "<(node_root_dir)/deps/openssl/config/arm" ]
}],
['grpc_alpn=="true"', { ['grpc_alpn=="true"', {
'defines': [ 'defines': [
'TSI_OPENSSL_ALPN_SUPPORT=1' 'TSI_OPENSSL_ALPN_SUPPORT=1'
@ -127,17 +136,6 @@
], ],
'include_dirs': [ 'include_dirs': [
'<(node_root_dir)/deps/openssl/openssl/include', '<(node_root_dir)/deps/openssl/openssl/include',
],
'conditions': [
["target_arch=='ia32'", {
"include_dirs": [ "<(node_root_dir)/deps/openssl/config/piii" ]
}],
["target_arch=='x64'", {
"include_dirs": [ "<(node_root_dir)/deps/openssl/config/k8" ]
}],
["target_arch=='arm'", {
"include_dirs": [ "<(node_root_dir)/deps/openssl/config/arm" ]
}]
] ]
}], }],
['OS == "win"', { ['OS == "win"', {
@ -174,6 +172,7 @@
'targets': [ 'targets': [
{ {
'cflags': [ 'cflags': [
'-std=c++11',
'-std=c99', '-std=c99',
'-Wall', '-Wall',
'-Werror' '-Werror'
@ -186,6 +185,7 @@
'sources': [ 'sources': [
'src/boringssl/err_data.c', 'src/boringssl/err_data.c',
'third_party/boringssl/crypto/aes/aes.c', 'third_party/boringssl/crypto/aes/aes.c',
'third_party/boringssl/crypto/aes/key_wrap.c',
'third_party/boringssl/crypto/aes/mode_wrappers.c', 'third_party/boringssl/crypto/aes/mode_wrappers.c',
'third_party/boringssl/crypto/asn1/a_bitstr.c', 'third_party/boringssl/crypto/asn1/a_bitstr.c',
'third_party/boringssl/crypto/asn1/a_bool.c', 'third_party/boringssl/crypto/asn1/a_bool.c',
@ -217,12 +217,12 @@
'third_party/boringssl/crypto/asn1/tasn_new.c', 'third_party/boringssl/crypto/asn1/tasn_new.c',
'third_party/boringssl/crypto/asn1/tasn_typ.c', 'third_party/boringssl/crypto/asn1/tasn_typ.c',
'third_party/boringssl/crypto/asn1/tasn_utl.c', 'third_party/boringssl/crypto/asn1/tasn_utl.c',
'third_party/boringssl/crypto/asn1/time_support.c',
'third_party/boringssl/crypto/asn1/x_bignum.c', 'third_party/boringssl/crypto/asn1/x_bignum.c',
'third_party/boringssl/crypto/asn1/x_long.c', 'third_party/boringssl/crypto/asn1/x_long.c',
'third_party/boringssl/crypto/base64/base64.c', 'third_party/boringssl/crypto/base64/base64.c',
'third_party/boringssl/crypto/bio/bio.c', 'third_party/boringssl/crypto/bio/bio.c',
'third_party/boringssl/crypto/bio/bio_mem.c', 'third_party/boringssl/crypto/bio/bio_mem.c',
'third_party/boringssl/crypto/bio/buffer.c',
'third_party/boringssl/crypto/bio/connect.c', 'third_party/boringssl/crypto/bio/connect.c',
'third_party/boringssl/crypto/bio/fd.c', 'third_party/boringssl/crypto/bio/fd.c',
'third_party/boringssl/crypto/bio/file.c', 'third_party/boringssl/crypto/bio/file.c',
@ -329,12 +329,7 @@
'third_party/boringssl/crypto/modes/ctr.c', 'third_party/boringssl/crypto/modes/ctr.c',
'third_party/boringssl/crypto/modes/gcm.c', 'third_party/boringssl/crypto/modes/gcm.c',
'third_party/boringssl/crypto/modes/ofb.c', 'third_party/boringssl/crypto/modes/ofb.c',
'third_party/boringssl/crypto/newhope/error_correction.c', 'third_party/boringssl/crypto/modes/polyval.c',
'third_party/boringssl/crypto/newhope/newhope.c',
'third_party/boringssl/crypto/newhope/ntt.c',
'third_party/boringssl/crypto/newhope/poly.c',
'third_party/boringssl/crypto/newhope/precomp.c',
'third_party/boringssl/crypto/newhope/reduce.c',
'third_party/boringssl/crypto/obj/obj.c', 'third_party/boringssl/crypto/obj/obj.c',
'third_party/boringssl/crypto/obj/obj_xref.c', 'third_party/boringssl/crypto/obj/obj_xref.c',
'third_party/boringssl/crypto/pem/pem_all.c', 'third_party/boringssl/crypto/pem/pem_all.c',
@ -345,14 +340,15 @@
'third_party/boringssl/crypto/pem/pem_pkey.c', 'third_party/boringssl/crypto/pem/pem_pkey.c',
'third_party/boringssl/crypto/pem/pem_x509.c', 'third_party/boringssl/crypto/pem/pem_x509.c',
'third_party/boringssl/crypto/pem/pem_xaux.c', 'third_party/boringssl/crypto/pem/pem_xaux.c',
'third_party/boringssl/crypto/pkcs8/p5_pbe.c',
'third_party/boringssl/crypto/pkcs8/p5_pbev2.c', 'third_party/boringssl/crypto/pkcs8/p5_pbev2.c',
'third_party/boringssl/crypto/pkcs8/p8_pkey.c', 'third_party/boringssl/crypto/pkcs8/p8_pkey.c',
'third_party/boringssl/crypto/pkcs8/pkcs8.c', 'third_party/boringssl/crypto/pkcs8/pkcs8.c',
'third_party/boringssl/crypto/poly1305/poly1305.c', 'third_party/boringssl/crypto/poly1305/poly1305.c',
'third_party/boringssl/crypto/poly1305/poly1305_arm.c', 'third_party/boringssl/crypto/poly1305/poly1305_arm.c',
'third_party/boringssl/crypto/poly1305/poly1305_vec.c', 'third_party/boringssl/crypto/poly1305/poly1305_vec.c',
'third_party/boringssl/crypto/pool/pool.c',
'third_party/boringssl/crypto/rand/deterministic.c', 'third_party/boringssl/crypto/rand/deterministic.c',
'third_party/boringssl/crypto/rand/fuchsia.c',
'third_party/boringssl/crypto/rand/rand.c', 'third_party/boringssl/crypto/rand/rand.c',
'third_party/boringssl/crypto/rand/urandom.c', 'third_party/boringssl/crypto/rand/urandom.c',
'third_party/boringssl/crypto/rand/windows.c', 'third_party/boringssl/crypto/rand/windows.c',
@ -364,6 +360,7 @@
'third_party/boringssl/crypto/rsa/rsa.c', 'third_party/boringssl/crypto/rsa/rsa.c',
'third_party/boringssl/crypto/rsa/rsa_asn1.c', 'third_party/boringssl/crypto/rsa/rsa_asn1.c',
'third_party/boringssl/crypto/rsa/rsa_impl.c', 'third_party/boringssl/crypto/rsa/rsa_impl.c',
'third_party/boringssl/crypto/sha/sha1-altivec.c',
'third_party/boringssl/crypto/sha/sha1.c', 'third_party/boringssl/crypto/sha/sha1.c',
'third_party/boringssl/crypto/sha/sha256.c', 'third_party/boringssl/crypto/sha/sha256.c',
'third_party/boringssl/crypto/sha/sha512.c', 'third_party/boringssl/crypto/sha/sha512.c',
@ -372,7 +369,6 @@
'third_party/boringssl/crypto/thread_none.c', 'third_party/boringssl/crypto/thread_none.c',
'third_party/boringssl/crypto/thread_pthread.c', 'third_party/boringssl/crypto/thread_pthread.c',
'third_party/boringssl/crypto/thread_win.c', 'third_party/boringssl/crypto/thread_win.c',
'third_party/boringssl/crypto/time_support.c',
'third_party/boringssl/crypto/x509/a_digest.c', 'third_party/boringssl/crypto/x509/a_digest.c',
'third_party/boringssl/crypto/x509/a_sign.c', 'third_party/boringssl/crypto/x509/a_sign.c',
'third_party/boringssl/crypto/x509/a_strex.c', 'third_party/boringssl/crypto/x509/a_strex.c',
@ -456,6 +452,7 @@
'third_party/boringssl/crypto/x509v3/v3_skey.c', 'third_party/boringssl/crypto/x509v3/v3_skey.c',
'third_party/boringssl/crypto/x509v3/v3_sxnet.c', 'third_party/boringssl/crypto/x509v3/v3_sxnet.c',
'third_party/boringssl/crypto/x509v3/v3_utl.c', 'third_party/boringssl/crypto/x509v3/v3_utl.c',
'third_party/boringssl/ssl/bio_ssl.c',
'third_party/boringssl/ssl/custom_extensions.c', 'third_party/boringssl/ssl/custom_extensions.c',
'third_party/boringssl/ssl/d1_both.c', 'third_party/boringssl/ssl/d1_both.c',
'third_party/boringssl/ssl/d1_lib.c', 'third_party/boringssl/ssl/d1_lib.c',
@ -466,7 +463,6 @@
'third_party/boringssl/ssl/handshake_client.c', 'third_party/boringssl/ssl/handshake_client.c',
'third_party/boringssl/ssl/handshake_server.c', 'third_party/boringssl/ssl/handshake_server.c',
'third_party/boringssl/ssl/s3_both.c', 'third_party/boringssl/ssl/s3_both.c',
'third_party/boringssl/ssl/s3_enc.c',
'third_party/boringssl/ssl/s3_lib.c', 'third_party/boringssl/ssl/s3_lib.c',
'third_party/boringssl/ssl/s3_pkt.c', 'third_party/boringssl/ssl/s3_pkt.c',
'third_party/boringssl/ssl/ssl_aead_ctx.c', 'third_party/boringssl/ssl/ssl_aead_ctx.c',
@ -477,9 +473,12 @@
'third_party/boringssl/ssl/ssl_ecdh.c', 'third_party/boringssl/ssl/ssl_ecdh.c',
'third_party/boringssl/ssl/ssl_file.c', 'third_party/boringssl/ssl/ssl_file.c',
'third_party/boringssl/ssl/ssl_lib.c', 'third_party/boringssl/ssl/ssl_lib.c',
'third_party/boringssl/ssl/ssl_rsa.c', 'third_party/boringssl/ssl/ssl_privkey.c',
'third_party/boringssl/ssl/ssl_privkey_cc.cc',
'third_party/boringssl/ssl/ssl_session.c', 'third_party/boringssl/ssl/ssl_session.c',
'third_party/boringssl/ssl/ssl_stat.c', 'third_party/boringssl/ssl/ssl_stat.c',
'third_party/boringssl/ssl/ssl_transcript.c',
'third_party/boringssl/ssl/ssl_x509.c',
'third_party/boringssl/ssl/t1_enc.c', 'third_party/boringssl/ssl/t1_enc.c',
'third_party/boringssl/ssl/t1_lib.c', 'third_party/boringssl/ssl/t1_lib.c',
'third_party/boringssl/ssl/tls13_both.c', 'third_party/boringssl/ssl/tls13_both.c',
@ -488,9 +487,20 @@
'third_party/boringssl/ssl/tls13_server.c', 'third_party/boringssl/ssl/tls13_server.c',
'third_party/boringssl/ssl/tls_method.c', 'third_party/boringssl/ssl/tls_method.c',
'third_party/boringssl/ssl/tls_record.c', 'third_party/boringssl/ssl/tls_record.c',
] ],
'conditions': [
['OS=="mac"', {
'xcode_settings': {
'MACOSX_DEPLOYMENT_TARGET': '10.9',
'OTHER_CPLUSPLUSFLAGS': [
'-stdlib=libc++',
'-std=c++11'
],
}
}],
],
}, },
] ],
}], }],
['OS == "win" and runtime!="electron"', { ['OS == "win" and runtime!="electron"', {
'targets': [ 'targets': [
@ -594,7 +604,6 @@
'src/core/lib/support/log_windows.c', 'src/core/lib/support/log_windows.c',
'src/core/lib/support/mpscq.c', 'src/core/lib/support/mpscq.c',
'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/murmur_hash.c',
'src/core/lib/support/stack_lockfree.c',
'src/core/lib/support/string.c', 'src/core/lib/support/string.c',
'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_posix.c',
'src/core/lib/support/string_util_windows.c', 'src/core/lib/support/string_util_windows.c',

@ -99,7 +99,6 @@ filegroups:
- src/core/lib/support/mpscq.h - src/core/lib/support/mpscq.h
- src/core/lib/support/murmur_hash.h - src/core/lib/support/murmur_hash.h
- src/core/lib/support/spinlock.h - src/core/lib/support/spinlock.h
- src/core/lib/support/stack_lockfree.h
- src/core/lib/support/string.h - src/core/lib/support/string.h
- src/core/lib/support/string_windows.h - src/core/lib/support/string_windows.h
- src/core/lib/support/thd_internal.h - src/core/lib/support/thd_internal.h
@ -130,7 +129,6 @@ filegroups:
- src/core/lib/support/log_windows.c - src/core/lib/support/log_windows.c
- src/core/lib/support/mpscq.c - src/core/lib/support/mpscq.c
- src/core/lib/support/murmur_hash.c - src/core/lib/support/murmur_hash.c
- src/core/lib/support/stack_lockfree.c
- src/core/lib/support/string.c - src/core/lib/support/string.c
- src/core/lib/support/string_posix.c - src/core/lib/support/string_posix.c
- src/core/lib/support/string_util_windows.c - src/core/lib/support/string_util_windows.c
@ -2123,15 +2121,6 @@ targets:
deps: deps:
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: gpr_stack_lockfree_test
cpu_cost: 7
build: test
language: c
src:
- test/core/support/stack_lockfree_test.c
deps:
- gpr_test_util
- gpr
- name: gpr_string_test - name: gpr_string_test
build: test build: test
language: c language: c

@ -63,7 +63,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/support/log_windows.c \ src/core/lib/support/log_windows.c \
src/core/lib/support/mpscq.c \ src/core/lib/support/mpscq.c \
src/core/lib/support/murmur_hash.c \ src/core/lib/support/murmur_hash.c \
src/core/lib/support/stack_lockfree.c \
src/core/lib/support/string.c \ src/core/lib/support/string.c \
src/core/lib/support/string_posix.c \ src/core/lib/support/string_posix.c \
src/core/lib/support/string_util_windows.c \ src/core/lib/support/string_util_windows.c \
@ -336,6 +335,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/plugin_registry/grpc_plugin_registry.c \ src/core/plugin_registry/grpc_plugin_registry.c \
src/boringssl/err_data.c \ src/boringssl/err_data.c \
third_party/boringssl/crypto/aes/aes.c \ third_party/boringssl/crypto/aes/aes.c \
third_party/boringssl/crypto/aes/key_wrap.c \
third_party/boringssl/crypto/aes/mode_wrappers.c \ third_party/boringssl/crypto/aes/mode_wrappers.c \
third_party/boringssl/crypto/asn1/a_bitstr.c \ third_party/boringssl/crypto/asn1/a_bitstr.c \
third_party/boringssl/crypto/asn1/a_bool.c \ third_party/boringssl/crypto/asn1/a_bool.c \
@ -367,12 +367,12 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/crypto/asn1/tasn_new.c \ third_party/boringssl/crypto/asn1/tasn_new.c \
third_party/boringssl/crypto/asn1/tasn_typ.c \ third_party/boringssl/crypto/asn1/tasn_typ.c \
third_party/boringssl/crypto/asn1/tasn_utl.c \ third_party/boringssl/crypto/asn1/tasn_utl.c \
third_party/boringssl/crypto/asn1/time_support.c \
third_party/boringssl/crypto/asn1/x_bignum.c \ third_party/boringssl/crypto/asn1/x_bignum.c \
third_party/boringssl/crypto/asn1/x_long.c \ third_party/boringssl/crypto/asn1/x_long.c \
third_party/boringssl/crypto/base64/base64.c \ third_party/boringssl/crypto/base64/base64.c \
third_party/boringssl/crypto/bio/bio.c \ third_party/boringssl/crypto/bio/bio.c \
third_party/boringssl/crypto/bio/bio_mem.c \ third_party/boringssl/crypto/bio/bio_mem.c \
third_party/boringssl/crypto/bio/buffer.c \
third_party/boringssl/crypto/bio/connect.c \ third_party/boringssl/crypto/bio/connect.c \
third_party/boringssl/crypto/bio/fd.c \ third_party/boringssl/crypto/bio/fd.c \
third_party/boringssl/crypto/bio/file.c \ third_party/boringssl/crypto/bio/file.c \
@ -479,12 +479,7 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/crypto/modes/ctr.c \ third_party/boringssl/crypto/modes/ctr.c \
third_party/boringssl/crypto/modes/gcm.c \ third_party/boringssl/crypto/modes/gcm.c \
third_party/boringssl/crypto/modes/ofb.c \ third_party/boringssl/crypto/modes/ofb.c \
third_party/boringssl/crypto/newhope/error_correction.c \ third_party/boringssl/crypto/modes/polyval.c \
third_party/boringssl/crypto/newhope/newhope.c \
third_party/boringssl/crypto/newhope/ntt.c \
third_party/boringssl/crypto/newhope/poly.c \
third_party/boringssl/crypto/newhope/precomp.c \
third_party/boringssl/crypto/newhope/reduce.c \
third_party/boringssl/crypto/obj/obj.c \ third_party/boringssl/crypto/obj/obj.c \
third_party/boringssl/crypto/obj/obj_xref.c \ third_party/boringssl/crypto/obj/obj_xref.c \
third_party/boringssl/crypto/pem/pem_all.c \ third_party/boringssl/crypto/pem/pem_all.c \
@ -495,14 +490,15 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/crypto/pem/pem_pkey.c \ third_party/boringssl/crypto/pem/pem_pkey.c \
third_party/boringssl/crypto/pem/pem_x509.c \ third_party/boringssl/crypto/pem/pem_x509.c \
third_party/boringssl/crypto/pem/pem_xaux.c \ third_party/boringssl/crypto/pem/pem_xaux.c \
third_party/boringssl/crypto/pkcs8/p5_pbe.c \
third_party/boringssl/crypto/pkcs8/p5_pbev2.c \ third_party/boringssl/crypto/pkcs8/p5_pbev2.c \
third_party/boringssl/crypto/pkcs8/p8_pkey.c \ third_party/boringssl/crypto/pkcs8/p8_pkey.c \
third_party/boringssl/crypto/pkcs8/pkcs8.c \ third_party/boringssl/crypto/pkcs8/pkcs8.c \
third_party/boringssl/crypto/poly1305/poly1305.c \ third_party/boringssl/crypto/poly1305/poly1305.c \
third_party/boringssl/crypto/poly1305/poly1305_arm.c \ third_party/boringssl/crypto/poly1305/poly1305_arm.c \
third_party/boringssl/crypto/poly1305/poly1305_vec.c \ third_party/boringssl/crypto/poly1305/poly1305_vec.c \
third_party/boringssl/crypto/pool/pool.c \
third_party/boringssl/crypto/rand/deterministic.c \ third_party/boringssl/crypto/rand/deterministic.c \
third_party/boringssl/crypto/rand/fuchsia.c \
third_party/boringssl/crypto/rand/rand.c \ third_party/boringssl/crypto/rand/rand.c \
third_party/boringssl/crypto/rand/urandom.c \ third_party/boringssl/crypto/rand/urandom.c \
third_party/boringssl/crypto/rand/windows.c \ third_party/boringssl/crypto/rand/windows.c \
@ -514,6 +510,7 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/crypto/rsa/rsa.c \ third_party/boringssl/crypto/rsa/rsa.c \
third_party/boringssl/crypto/rsa/rsa_asn1.c \ third_party/boringssl/crypto/rsa/rsa_asn1.c \
third_party/boringssl/crypto/rsa/rsa_impl.c \ third_party/boringssl/crypto/rsa/rsa_impl.c \
third_party/boringssl/crypto/sha/sha1-altivec.c \
third_party/boringssl/crypto/sha/sha1.c \ third_party/boringssl/crypto/sha/sha1.c \
third_party/boringssl/crypto/sha/sha256.c \ third_party/boringssl/crypto/sha/sha256.c \
third_party/boringssl/crypto/sha/sha512.c \ third_party/boringssl/crypto/sha/sha512.c \
@ -522,7 +519,6 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/crypto/thread_none.c \ third_party/boringssl/crypto/thread_none.c \
third_party/boringssl/crypto/thread_pthread.c \ third_party/boringssl/crypto/thread_pthread.c \
third_party/boringssl/crypto/thread_win.c \ third_party/boringssl/crypto/thread_win.c \
third_party/boringssl/crypto/time_support.c \
third_party/boringssl/crypto/x509/a_digest.c \ third_party/boringssl/crypto/x509/a_digest.c \
third_party/boringssl/crypto/x509/a_sign.c \ third_party/boringssl/crypto/x509/a_sign.c \
third_party/boringssl/crypto/x509/a_strex.c \ third_party/boringssl/crypto/x509/a_strex.c \
@ -606,6 +602,7 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/crypto/x509v3/v3_skey.c \ third_party/boringssl/crypto/x509v3/v3_skey.c \
third_party/boringssl/crypto/x509v3/v3_sxnet.c \ third_party/boringssl/crypto/x509v3/v3_sxnet.c \
third_party/boringssl/crypto/x509v3/v3_utl.c \ third_party/boringssl/crypto/x509v3/v3_utl.c \
third_party/boringssl/ssl/bio_ssl.c \
third_party/boringssl/ssl/custom_extensions.c \ third_party/boringssl/ssl/custom_extensions.c \
third_party/boringssl/ssl/d1_both.c \ third_party/boringssl/ssl/d1_both.c \
third_party/boringssl/ssl/d1_lib.c \ third_party/boringssl/ssl/d1_lib.c \
@ -616,7 +613,6 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/ssl/handshake_client.c \ third_party/boringssl/ssl/handshake_client.c \
third_party/boringssl/ssl/handshake_server.c \ third_party/boringssl/ssl/handshake_server.c \
third_party/boringssl/ssl/s3_both.c \ third_party/boringssl/ssl/s3_both.c \
third_party/boringssl/ssl/s3_enc.c \
third_party/boringssl/ssl/s3_lib.c \ third_party/boringssl/ssl/s3_lib.c \
third_party/boringssl/ssl/s3_pkt.c \ third_party/boringssl/ssl/s3_pkt.c \
third_party/boringssl/ssl/ssl_aead_ctx.c \ third_party/boringssl/ssl/ssl_aead_ctx.c \
@ -627,9 +623,12 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/ssl/ssl_ecdh.c \ third_party/boringssl/ssl/ssl_ecdh.c \
third_party/boringssl/ssl/ssl_file.c \ third_party/boringssl/ssl/ssl_file.c \
third_party/boringssl/ssl/ssl_lib.c \ third_party/boringssl/ssl/ssl_lib.c \
third_party/boringssl/ssl/ssl_rsa.c \ third_party/boringssl/ssl/ssl_privkey.c \
third_party/boringssl/ssl/ssl_privkey_cc.cc \
third_party/boringssl/ssl/ssl_session.c \ third_party/boringssl/ssl/ssl_session.c \
third_party/boringssl/ssl/ssl_stat.c \ third_party/boringssl/ssl/ssl_stat.c \
third_party/boringssl/ssl/ssl_transcript.c \
third_party/boringssl/ssl/ssl_x509.c \
third_party/boringssl/ssl/t1_enc.c \ third_party/boringssl/ssl/t1_enc.c \
third_party/boringssl/ssl/t1_lib.c \ third_party/boringssl/ssl/t1_lib.c \
third_party/boringssl/ssl/tls13_both.c \ third_party/boringssl/ssl/tls13_both.c \
@ -728,11 +727,11 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/md4) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/md4)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/md5) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/md5)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/modes) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/modes)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/newhope)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/obj) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/obj)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/pem) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/pem)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/pkcs8) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/pkcs8)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/poly1305) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/poly1305)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/pool)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/rand) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/rand)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/rc4) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/rc4)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/rsa) PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/rsa)

@ -40,7 +40,6 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\support\\log_windows.c " + "src\\core\\lib\\support\\log_windows.c " +
"src\\core\\lib\\support\\mpscq.c " + "src\\core\\lib\\support\\mpscq.c " +
"src\\core\\lib\\support\\murmur_hash.c " + "src\\core\\lib\\support\\murmur_hash.c " +
"src\\core\\lib\\support\\stack_lockfree.c " +
"src\\core\\lib\\support\\string.c " + "src\\core\\lib\\support\\string.c " +
"src\\core\\lib\\support\\string_posix.c " + "src\\core\\lib\\support\\string_posix.c " +
"src\\core\\lib\\support\\string_util_windows.c " + "src\\core\\lib\\support\\string_util_windows.c " +
@ -313,6 +312,7 @@ if (PHP_GRPC != "no") {
"src\\core\\plugin_registry\\grpc_plugin_registry.c " + "src\\core\\plugin_registry\\grpc_plugin_registry.c " +
"src\\boringssl\\err_data.c " + "src\\boringssl\\err_data.c " +
"third_party\\boringssl\\crypto\\aes\\aes.c " + "third_party\\boringssl\\crypto\\aes\\aes.c " +
"third_party\\boringssl\\crypto\\aes\\key_wrap.c " +
"third_party\\boringssl\\crypto\\aes\\mode_wrappers.c " + "third_party\\boringssl\\crypto\\aes\\mode_wrappers.c " +
"third_party\\boringssl\\crypto\\asn1\\a_bitstr.c " + "third_party\\boringssl\\crypto\\asn1\\a_bitstr.c " +
"third_party\\boringssl\\crypto\\asn1\\a_bool.c " + "third_party\\boringssl\\crypto\\asn1\\a_bool.c " +
@ -344,12 +344,12 @@ if (PHP_GRPC != "no") {
"third_party\\boringssl\\crypto\\asn1\\tasn_new.c " + "third_party\\boringssl\\crypto\\asn1\\tasn_new.c " +
"third_party\\boringssl\\crypto\\asn1\\tasn_typ.c " + "third_party\\boringssl\\crypto\\asn1\\tasn_typ.c " +
"third_party\\boringssl\\crypto\\asn1\\tasn_utl.c " + "third_party\\boringssl\\crypto\\asn1\\tasn_utl.c " +
"third_party\\boringssl\\crypto\\asn1\\time_support.c " +
"third_party\\boringssl\\crypto\\asn1\\x_bignum.c " + "third_party\\boringssl\\crypto\\asn1\\x_bignum.c " +
"third_party\\boringssl\\crypto\\asn1\\x_long.c " + "third_party\\boringssl\\crypto\\asn1\\x_long.c " +
"third_party\\boringssl\\crypto\\base64\\base64.c " + "third_party\\boringssl\\crypto\\base64\\base64.c " +
"third_party\\boringssl\\crypto\\bio\\bio.c " + "third_party\\boringssl\\crypto\\bio\\bio.c " +
"third_party\\boringssl\\crypto\\bio\\bio_mem.c " + "third_party\\boringssl\\crypto\\bio\\bio_mem.c " +
"third_party\\boringssl\\crypto\\bio\\buffer.c " +
"third_party\\boringssl\\crypto\\bio\\connect.c " + "third_party\\boringssl\\crypto\\bio\\connect.c " +
"third_party\\boringssl\\crypto\\bio\\fd.c " + "third_party\\boringssl\\crypto\\bio\\fd.c " +
"third_party\\boringssl\\crypto\\bio\\file.c " + "third_party\\boringssl\\crypto\\bio\\file.c " +
@ -456,12 +456,7 @@ if (PHP_GRPC != "no") {
"third_party\\boringssl\\crypto\\modes\\ctr.c " + "third_party\\boringssl\\crypto\\modes\\ctr.c " +
"third_party\\boringssl\\crypto\\modes\\gcm.c " + "third_party\\boringssl\\crypto\\modes\\gcm.c " +
"third_party\\boringssl\\crypto\\modes\\ofb.c " + "third_party\\boringssl\\crypto\\modes\\ofb.c " +
"third_party\\boringssl\\crypto\\newhope\\error_correction.c " + "third_party\\boringssl\\crypto\\modes\\polyval.c " +
"third_party\\boringssl\\crypto\\newhope\\newhope.c " +
"third_party\\boringssl\\crypto\\newhope\\ntt.c " +
"third_party\\boringssl\\crypto\\newhope\\poly.c " +
"third_party\\boringssl\\crypto\\newhope\\precomp.c " +
"third_party\\boringssl\\crypto\\newhope\\reduce.c " +
"third_party\\boringssl\\crypto\\obj\\obj.c " + "third_party\\boringssl\\crypto\\obj\\obj.c " +
"third_party\\boringssl\\crypto\\obj\\obj_xref.c " + "third_party\\boringssl\\crypto\\obj\\obj_xref.c " +
"third_party\\boringssl\\crypto\\pem\\pem_all.c " + "third_party\\boringssl\\crypto\\pem\\pem_all.c " +
@ -472,14 +467,15 @@ if (PHP_GRPC != "no") {
"third_party\\boringssl\\crypto\\pem\\pem_pkey.c " + "third_party\\boringssl\\crypto\\pem\\pem_pkey.c " +
"third_party\\boringssl\\crypto\\pem\\pem_x509.c " + "third_party\\boringssl\\crypto\\pem\\pem_x509.c " +
"third_party\\boringssl\\crypto\\pem\\pem_xaux.c " + "third_party\\boringssl\\crypto\\pem\\pem_xaux.c " +
"third_party\\boringssl\\crypto\\pkcs8\\p5_pbe.c " +
"third_party\\boringssl\\crypto\\pkcs8\\p5_pbev2.c " + "third_party\\boringssl\\crypto\\pkcs8\\p5_pbev2.c " +
"third_party\\boringssl\\crypto\\pkcs8\\p8_pkey.c " + "third_party\\boringssl\\crypto\\pkcs8\\p8_pkey.c " +
"third_party\\boringssl\\crypto\\pkcs8\\pkcs8.c " + "third_party\\boringssl\\crypto\\pkcs8\\pkcs8.c " +
"third_party\\boringssl\\crypto\\poly1305\\poly1305.c " + "third_party\\boringssl\\crypto\\poly1305\\poly1305.c " +
"third_party\\boringssl\\crypto\\poly1305\\poly1305_arm.c " + "third_party\\boringssl\\crypto\\poly1305\\poly1305_arm.c " +
"third_party\\boringssl\\crypto\\poly1305\\poly1305_vec.c " + "third_party\\boringssl\\crypto\\poly1305\\poly1305_vec.c " +
"third_party\\boringssl\\crypto\\pool\\pool.c " +
"third_party\\boringssl\\crypto\\rand\\deterministic.c " + "third_party\\boringssl\\crypto\\rand\\deterministic.c " +
"third_party\\boringssl\\crypto\\rand\\fuchsia.c " +
"third_party\\boringssl\\crypto\\rand\\rand.c " + "third_party\\boringssl\\crypto\\rand\\rand.c " +
"third_party\\boringssl\\crypto\\rand\\urandom.c " + "third_party\\boringssl\\crypto\\rand\\urandom.c " +
"third_party\\boringssl\\crypto\\rand\\windows.c " + "third_party\\boringssl\\crypto\\rand\\windows.c " +
@ -491,6 +487,7 @@ if (PHP_GRPC != "no") {
"third_party\\boringssl\\crypto\\rsa\\rsa.c " + "third_party\\boringssl\\crypto\\rsa\\rsa.c " +
"third_party\\boringssl\\crypto\\rsa\\rsa_asn1.c " + "third_party\\boringssl\\crypto\\rsa\\rsa_asn1.c " +
"third_party\\boringssl\\crypto\\rsa\\rsa_impl.c " + "third_party\\boringssl\\crypto\\rsa\\rsa_impl.c " +
"third_party\\boringssl\\crypto\\sha\\sha1-altivec.c " +
"third_party\\boringssl\\crypto\\sha\\sha1.c " + "third_party\\boringssl\\crypto\\sha\\sha1.c " +
"third_party\\boringssl\\crypto\\sha\\sha256.c " + "third_party\\boringssl\\crypto\\sha\\sha256.c " +
"third_party\\boringssl\\crypto\\sha\\sha512.c " + "third_party\\boringssl\\crypto\\sha\\sha512.c " +
@ -499,7 +496,6 @@ if (PHP_GRPC != "no") {
"third_party\\boringssl\\crypto\\thread_none.c " + "third_party\\boringssl\\crypto\\thread_none.c " +
"third_party\\boringssl\\crypto\\thread_pthread.c " + "third_party\\boringssl\\crypto\\thread_pthread.c " +
"third_party\\boringssl\\crypto\\thread_win.c " + "third_party\\boringssl\\crypto\\thread_win.c " +
"third_party\\boringssl\\crypto\\time_support.c " +
"third_party\\boringssl\\crypto\\x509\\a_digest.c " + "third_party\\boringssl\\crypto\\x509\\a_digest.c " +
"third_party\\boringssl\\crypto\\x509\\a_sign.c " + "third_party\\boringssl\\crypto\\x509\\a_sign.c " +
"third_party\\boringssl\\crypto\\x509\\a_strex.c " + "third_party\\boringssl\\crypto\\x509\\a_strex.c " +
@ -583,6 +579,7 @@ if (PHP_GRPC != "no") {
"third_party\\boringssl\\crypto\\x509v3\\v3_skey.c " + "third_party\\boringssl\\crypto\\x509v3\\v3_skey.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_sxnet.c " + "third_party\\boringssl\\crypto\\x509v3\\v3_sxnet.c " +
"third_party\\boringssl\\crypto\\x509v3\\v3_utl.c " + "third_party\\boringssl\\crypto\\x509v3\\v3_utl.c " +
"third_party\\boringssl\\ssl\\bio_ssl.c " +
"third_party\\boringssl\\ssl\\custom_extensions.c " + "third_party\\boringssl\\ssl\\custom_extensions.c " +
"third_party\\boringssl\\ssl\\d1_both.c " + "third_party\\boringssl\\ssl\\d1_both.c " +
"third_party\\boringssl\\ssl\\d1_lib.c " + "third_party\\boringssl\\ssl\\d1_lib.c " +
@ -593,7 +590,6 @@ if (PHP_GRPC != "no") {
"third_party\\boringssl\\ssl\\handshake_client.c " + "third_party\\boringssl\\ssl\\handshake_client.c " +
"third_party\\boringssl\\ssl\\handshake_server.c " + "third_party\\boringssl\\ssl\\handshake_server.c " +
"third_party\\boringssl\\ssl\\s3_both.c " + "third_party\\boringssl\\ssl\\s3_both.c " +
"third_party\\boringssl\\ssl\\s3_enc.c " +
"third_party\\boringssl\\ssl\\s3_lib.c " + "third_party\\boringssl\\ssl\\s3_lib.c " +
"third_party\\boringssl\\ssl\\s3_pkt.c " + "third_party\\boringssl\\ssl\\s3_pkt.c " +
"third_party\\boringssl\\ssl\\ssl_aead_ctx.c " + "third_party\\boringssl\\ssl\\ssl_aead_ctx.c " +
@ -604,9 +600,12 @@ if (PHP_GRPC != "no") {
"third_party\\boringssl\\ssl\\ssl_ecdh.c " + "third_party\\boringssl\\ssl\\ssl_ecdh.c " +
"third_party\\boringssl\\ssl\\ssl_file.c " + "third_party\\boringssl\\ssl\\ssl_file.c " +
"third_party\\boringssl\\ssl\\ssl_lib.c " + "third_party\\boringssl\\ssl\\ssl_lib.c " +
"third_party\\boringssl\\ssl\\ssl_rsa.c " + "third_party\\boringssl\\ssl\\ssl_privkey.c " +
"third_party\\boringssl\\ssl\\ssl_privkey_cc.cc " +
"third_party\\boringssl\\ssl\\ssl_session.c " + "third_party\\boringssl\\ssl\\ssl_session.c " +
"third_party\\boringssl\\ssl\\ssl_stat.c " + "third_party\\boringssl\\ssl\\ssl_stat.c " +
"third_party\\boringssl\\ssl\\ssl_transcript.c " +
"third_party\\boringssl\\ssl\\ssl_x509.c " +
"third_party\\boringssl\\ssl\\t1_enc.c " + "third_party\\boringssl\\ssl\\t1_enc.c " +
"third_party\\boringssl\\ssl\\t1_lib.c " + "third_party\\boringssl\\ssl\\t1_lib.c " +
"third_party\\boringssl\\ssl\\tls13_both.c " + "third_party\\boringssl\\ssl\\tls13_both.c " +
@ -640,4 +639,134 @@ if (PHP_GRPC != "no") {
"/I"+configure_module_dirname+"\\src\\php\\ext\\grpc "+ "/I"+configure_module_dirname+"\\src\\php\\ext\\grpc "+
"/I"+configure_module_dirname+"\\third_party\\boringssl\\include "+ "/I"+configure_module_dirname+"\\third_party\\boringssl\\include "+
"/I"+configure_module_dirname+"\\third_party\\zlib"); "/I"+configure_module_dirname+"\\third_party\\zlib");
base_dir = get_define('BUILD_DIR');
FSO.CreateFolder(base_dir+"\\ext");
FSO.CreateFolder(base_dir+"\\ext\\grpc");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\boringssl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\census");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\census\\gen");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\round_robin");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\fake");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\sockaddr");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\deadline");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http\\client");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http\\message_compress");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http\\server");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\load_reporting");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\max_age");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\message_size");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\workarounds");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\alpn");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\client");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\client\\insecure");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\client\\secure");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\server");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\server\\insecure");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\server\\secure");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\chttp2\\transport");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\channel");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\compression");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\debug");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\http");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\iomgr");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\json");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\profiling");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\context");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\composite");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\fake");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\google_default");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\iam");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\jwt");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\oauth2");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\plugin");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\ssl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\transport");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\util");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\slice");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\support");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\surface");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\transport");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\plugin_registry");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext\\grpc");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\aes");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\asn1");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\base64");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\bio");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\bn");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\bn\\asm");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\buf");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\bytestring");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\chacha");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\cipher");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\cmac");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\conf");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\curve25519");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\des");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\dh");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\digest");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\dsa");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\ec");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\ecdh");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\ecdsa");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\engine");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\err");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\evp");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\hkdf");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\hmac");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\lhash");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\md4");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\md5");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\modes");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\obj");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\pem");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\pkcs8");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\poly1305");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\pool");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\rand");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\rc4");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\rsa");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\sha");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\stack");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\x509");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\crypto\\x509v3");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\boringssl\\ssl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\nanopb");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\zlib");
_build_dirs = new Array();
for (i = 0; i < build_dirs.length; i++) {
if (build_dirs[i].indexOf('grpc') == -1) {
_build_dirs[_build_dirs.length] = build_dirs[i];
}
}
build_dirs = _build_dirs;
} }

@ -24,7 +24,8 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
* **Call-Definition** → Method Scheme Path TE [Authority] [Timeout] Content-Type [Message-Type] [Message-Encoding] [Message-Accept-Encoding] [User-Agent] * **Call-Definition** → Method Scheme Path TE [Authority] [Timeout] Content-Type [Message-Type] [Message-Encoding] [Message-Accept-Encoding] [User-Agent]
* **Method** → ":method POST" * **Method** → ":method POST"
* **Scheme** → ":scheme " ("http" / "https") * **Scheme** → ":scheme " ("http" / "https")
* **Path** → ":path" {_path identifying method within exposed API_} * **Path** → ":path" "/" Service-Name "/" {_method name_}
* **Service-Name** → {_IDL-specific service name_}
* **Authority** → ":authority" {_virtual host name of authority_} * **Authority** → ":authority" {_virtual host name of authority_}
* **TE** → "te" "trailers" # Used to detect incompatible proxies * **TE** → "te" "trailers" # Used to detect incompatible proxies
* **Timeout** → "grpc-timeout" TimeoutValue TimeoutUnit * **Timeout** → "grpc-timeout" TimeoutValue TimeoutUnit
@ -51,6 +52,13 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
HTTP2 requires that reserved headers, ones starting with ":" appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**. HTTP2 requires that reserved headers, ones starting with ":" appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**.
Some gRPC implementations may allow the **Path** format shown above
to be overridden, but this functionality is strongly discouraged.
gRPC does not go out of its way to break users that are using this kind
of override, but we do not actively support it, and some functionality
(e.g., service config support) will not work when the path is not of
the form shown above.
If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements. If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements.
**Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Header names starting with "grpc-" but not listed here are reserved for future GRPC use and should not be used by applications as **Custom-Metadata**. **Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Header names starting with "grpc-" but not listed here are reserved for future GRPC use and should not be used by applications as **Custom-Metadata**.
@ -238,10 +246,10 @@ If a detectable connection failure occurs on the client all calls will be closed
### Appendix A - GRPC for Protobuf ### Appendix A - GRPC for Protobuf
The service interfaces declared by protobuf are easily mapped onto GRPC by code generation extensions to protoc. The following defines the mapping to be used The service interfaces declared by protobuf are easily mapped onto GRPC by
code generation extensions to protoc. The following defines the mapping
to be used.
* **Path** → / Service-Name / {_method name_}
* **Service-Name** → ?( {_proto package name_} "." ) {_service name_} * **Service-Name** → ?( {_proto package name_} "." ) {_service name_}
* **Message-Type** → {_fully qualified proto message name_} * **Message-Type** → {_fully qualified proto message name_}
* **Content-Type** → "application/grpc+proto" * **Content-Type** → "application/grpc+proto"

@ -51,8 +51,6 @@ some configuration as environment variables that can be set.
- flowctl - traces http2 flow control - flowctl - traces http2 flow control
- op_failure - traces error information when failure is pushed onto a - op_failure - traces error information when failure is pushed onto a
completion queue completion queue
- pending_tags - [debug builds only] traces still-in-progress tags on
completion queues
- round_robin - traces the round_robin load balancing policy - round_robin - traces the round_robin load balancing policy
- glb - traces the grpclb load balancer - glb - traces the grpclb load balancer
- queue_pluck - queue_pluck
@ -63,6 +61,23 @@ some configuration as environment variables that can be set.
- transport_security - traces metadata about secure channel establishment - transport_security - traces metadata about secure channel establishment
- tcp - traces bytes in and out of a channel - tcp - traces bytes in and out of a channel
The following tracers will only run in binaries built in DEBUG mode. This is
accomplished by invoking `CONFIG=dbg make <target>`
- metadata - tracks creation and mutation of metadata
- closure - tracks closure creation, scheduling, and completion
- pending_tags - traces still-in-progress tags on completion queues
- polling - traces the selected polling engine
- queue_refcount
- error_refcount
- stream_refcount
- workqueue_refcount
- fd_refcount
- auth_context_refcount
- security_connector_refcount
- resolver_refcount
- lb_policy_refcount
- chttp2_refcount
'all' can additionally be used to turn all traces on. 'all' can additionally be used to turn all traces on.
Individual traces can be disabled by prefixing them with '-'. Individual traces can be disabled by prefixing them with '-'.

@ -193,7 +193,6 @@ Pod::Spec.new do |s|
'src/core/lib/support/mpscq.h', 'src/core/lib/support/mpscq.h',
'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/murmur_hash.h',
'src/core/lib/support/spinlock.h', 'src/core/lib/support/spinlock.h',
'src/core/lib/support/stack_lockfree.h',
'src/core/lib/support/string.h', 'src/core/lib/support/string.h',
'src/core/lib/support/string_windows.h', 'src/core/lib/support/string_windows.h',
'src/core/lib/support/thd_internal.h', 'src/core/lib/support/thd_internal.h',
@ -223,7 +222,6 @@ Pod::Spec.new do |s|
'src/core/lib/support/log_windows.c', 'src/core/lib/support/log_windows.c',
'src/core/lib/support/mpscq.c', 'src/core/lib/support/mpscq.c',
'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/murmur_hash.c',
'src/core/lib/support/stack_lockfree.c',
'src/core/lib/support/string.c', 'src/core/lib/support/string.c',
'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_posix.c',
'src/core/lib/support/string_util_windows.c', 'src/core/lib/support/string_util_windows.c',
@ -723,7 +721,6 @@ Pod::Spec.new do |s|
'src/core/lib/support/mpscq.h', 'src/core/lib/support/mpscq.h',
'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/murmur_hash.h',
'src/core/lib/support/spinlock.h', 'src/core/lib/support/spinlock.h',
'src/core/lib/support/stack_lockfree.h',
'src/core/lib/support/string.h', 'src/core/lib/support/string.h',
'src/core/lib/support/string_windows.h', 'src/core/lib/support/string_windows.h',
'src/core/lib/support/thd_internal.h', 'src/core/lib/support/thd_internal.h',

@ -92,7 +92,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/mpscq.h ) s.files += %w( src/core/lib/support/mpscq.h )
s.files += %w( src/core/lib/support/murmur_hash.h ) s.files += %w( src/core/lib/support/murmur_hash.h )
s.files += %w( src/core/lib/support/spinlock.h ) s.files += %w( src/core/lib/support/spinlock.h )
s.files += %w( src/core/lib/support/stack_lockfree.h )
s.files += %w( src/core/lib/support/string.h ) s.files += %w( src/core/lib/support/string.h )
s.files += %w( src/core/lib/support/string_windows.h ) s.files += %w( src/core/lib/support/string_windows.h )
s.files += %w( src/core/lib/support/thd_internal.h ) s.files += %w( src/core/lib/support/thd_internal.h )
@ -122,7 +121,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/log_windows.c ) s.files += %w( src/core/lib/support/log_windows.c )
s.files += %w( src/core/lib/support/mpscq.c ) s.files += %w( src/core/lib/support/mpscq.c )
s.files += %w( src/core/lib/support/murmur_hash.c ) s.files += %w( src/core/lib/support/murmur_hash.c )
s.files += %w( src/core/lib/support/stack_lockfree.c )
s.files += %w( src/core/lib/support/string.c ) s.files += %w( src/core/lib/support/string.c )
s.files += %w( src/core/lib/support/string_posix.c ) s.files += %w( src/core/lib/support/string_posix.c )
s.files += %w( src/core/lib/support/string_util_windows.c ) s.files += %w( src/core/lib/support/string_util_windows.c )
@ -656,14 +654,14 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/crypto/digest/md32_common.h ) s.files += %w( third_party/boringssl/crypto/digest/md32_common.h )
s.files += %w( third_party/boringssl/crypto/ec/internal.h ) s.files += %w( third_party/boringssl/crypto/ec/internal.h )
s.files += %w( third_party/boringssl/crypto/ec/p256-x86_64-table.h ) s.files += %w( third_party/boringssl/crypto/ec/p256-x86_64-table.h )
s.files += %w( third_party/boringssl/crypto/ec/p256-x86_64.h )
s.files += %w( third_party/boringssl/crypto/evp/internal.h ) s.files += %w( third_party/boringssl/crypto/evp/internal.h )
s.files += %w( third_party/boringssl/crypto/internal.h ) s.files += %w( third_party/boringssl/crypto/internal.h )
s.files += %w( third_party/boringssl/crypto/modes/internal.h ) s.files += %w( third_party/boringssl/crypto/modes/internal.h )
s.files += %w( third_party/boringssl/crypto/newhope/internal.h )
s.files += %w( third_party/boringssl/crypto/obj/obj_dat.h ) s.files += %w( third_party/boringssl/crypto/obj/obj_dat.h )
s.files += %w( third_party/boringssl/crypto/obj/obj_xref.h )
s.files += %w( third_party/boringssl/crypto/pkcs8/internal.h ) s.files += %w( third_party/boringssl/crypto/pkcs8/internal.h )
s.files += %w( third_party/boringssl/crypto/poly1305/internal.h ) s.files += %w( third_party/boringssl/crypto/poly1305/internal.h )
s.files += %w( third_party/boringssl/crypto/pool/internal.h )
s.files += %w( third_party/boringssl/crypto/rand/internal.h ) s.files += %w( third_party/boringssl/crypto/rand/internal.h )
s.files += %w( third_party/boringssl/crypto/rsa/internal.h ) s.files += %w( third_party/boringssl/crypto/rsa/internal.h )
s.files += %w( third_party/boringssl/crypto/x509/charmap.h ) s.files += %w( third_party/boringssl/crypto/x509/charmap.h )
@ -713,7 +711,6 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/include/openssl/md4.h ) s.files += %w( third_party/boringssl/include/openssl/md4.h )
s.files += %w( third_party/boringssl/include/openssl/md5.h ) s.files += %w( third_party/boringssl/include/openssl/md5.h )
s.files += %w( third_party/boringssl/include/openssl/mem.h ) s.files += %w( third_party/boringssl/include/openssl/mem.h )
s.files += %w( third_party/boringssl/include/openssl/newhope.h )
s.files += %w( third_party/boringssl/include/openssl/nid.h ) s.files += %w( third_party/boringssl/include/openssl/nid.h )
s.files += %w( third_party/boringssl/include/openssl/obj.h ) s.files += %w( third_party/boringssl/include/openssl/obj.h )
s.files += %w( third_party/boringssl/include/openssl/obj_mac.h ) s.files += %w( third_party/boringssl/include/openssl/obj_mac.h )
@ -726,6 +723,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/include/openssl/pkcs7.h ) s.files += %w( third_party/boringssl/include/openssl/pkcs7.h )
s.files += %w( third_party/boringssl/include/openssl/pkcs8.h ) s.files += %w( third_party/boringssl/include/openssl/pkcs8.h )
s.files += %w( third_party/boringssl/include/openssl/poly1305.h ) s.files += %w( third_party/boringssl/include/openssl/poly1305.h )
s.files += %w( third_party/boringssl/include/openssl/pool.h )
s.files += %w( third_party/boringssl/include/openssl/rand.h ) s.files += %w( third_party/boringssl/include/openssl/rand.h )
s.files += %w( third_party/boringssl/include/openssl/rc4.h ) s.files += %w( third_party/boringssl/include/openssl/rc4.h )
s.files += %w( third_party/boringssl/include/openssl/ripemd.h ) s.files += %w( third_party/boringssl/include/openssl/ripemd.h )
@ -738,7 +736,6 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/include/openssl/stack.h ) s.files += %w( third_party/boringssl/include/openssl/stack.h )
s.files += %w( third_party/boringssl/include/openssl/stack_macros.h ) s.files += %w( third_party/boringssl/include/openssl/stack_macros.h )
s.files += %w( third_party/boringssl/include/openssl/thread.h ) s.files += %w( third_party/boringssl/include/openssl/thread.h )
s.files += %w( third_party/boringssl/include/openssl/time_support.h )
s.files += %w( third_party/boringssl/include/openssl/tls1.h ) s.files += %w( third_party/boringssl/include/openssl/tls1.h )
s.files += %w( third_party/boringssl/include/openssl/type_check.h ) s.files += %w( third_party/boringssl/include/openssl/type_check.h )
s.files += %w( third_party/boringssl/include/openssl/x509.h ) s.files += %w( third_party/boringssl/include/openssl/x509.h )
@ -747,6 +744,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/ssl/internal.h ) s.files += %w( third_party/boringssl/ssl/internal.h )
s.files += %w( src/boringssl/err_data.c ) s.files += %w( src/boringssl/err_data.c )
s.files += %w( third_party/boringssl/crypto/aes/aes.c ) s.files += %w( third_party/boringssl/crypto/aes/aes.c )
s.files += %w( third_party/boringssl/crypto/aes/key_wrap.c )
s.files += %w( third_party/boringssl/crypto/aes/mode_wrappers.c ) s.files += %w( third_party/boringssl/crypto/aes/mode_wrappers.c )
s.files += %w( third_party/boringssl/crypto/asn1/a_bitstr.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_bitstr.c )
s.files += %w( third_party/boringssl/crypto/asn1/a_bool.c ) s.files += %w( third_party/boringssl/crypto/asn1/a_bool.c )
@ -778,12 +776,12 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/crypto/asn1/tasn_new.c ) s.files += %w( third_party/boringssl/crypto/asn1/tasn_new.c )
s.files += %w( third_party/boringssl/crypto/asn1/tasn_typ.c ) s.files += %w( third_party/boringssl/crypto/asn1/tasn_typ.c )
s.files += %w( third_party/boringssl/crypto/asn1/tasn_utl.c ) s.files += %w( third_party/boringssl/crypto/asn1/tasn_utl.c )
s.files += %w( third_party/boringssl/crypto/asn1/time_support.c )
s.files += %w( third_party/boringssl/crypto/asn1/x_bignum.c ) s.files += %w( third_party/boringssl/crypto/asn1/x_bignum.c )
s.files += %w( third_party/boringssl/crypto/asn1/x_long.c ) s.files += %w( third_party/boringssl/crypto/asn1/x_long.c )
s.files += %w( third_party/boringssl/crypto/base64/base64.c ) s.files += %w( third_party/boringssl/crypto/base64/base64.c )
s.files += %w( third_party/boringssl/crypto/bio/bio.c ) s.files += %w( third_party/boringssl/crypto/bio/bio.c )
s.files += %w( third_party/boringssl/crypto/bio/bio_mem.c ) s.files += %w( third_party/boringssl/crypto/bio/bio_mem.c )
s.files += %w( third_party/boringssl/crypto/bio/buffer.c )
s.files += %w( third_party/boringssl/crypto/bio/connect.c ) s.files += %w( third_party/boringssl/crypto/bio/connect.c )
s.files += %w( third_party/boringssl/crypto/bio/fd.c ) s.files += %w( third_party/boringssl/crypto/bio/fd.c )
s.files += %w( third_party/boringssl/crypto/bio/file.c ) s.files += %w( third_party/boringssl/crypto/bio/file.c )
@ -890,12 +888,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/crypto/modes/ctr.c ) s.files += %w( third_party/boringssl/crypto/modes/ctr.c )
s.files += %w( third_party/boringssl/crypto/modes/gcm.c ) s.files += %w( third_party/boringssl/crypto/modes/gcm.c )
s.files += %w( third_party/boringssl/crypto/modes/ofb.c ) s.files += %w( third_party/boringssl/crypto/modes/ofb.c )
s.files += %w( third_party/boringssl/crypto/newhope/error_correction.c ) s.files += %w( third_party/boringssl/crypto/modes/polyval.c )
s.files += %w( third_party/boringssl/crypto/newhope/newhope.c )
s.files += %w( third_party/boringssl/crypto/newhope/ntt.c )
s.files += %w( third_party/boringssl/crypto/newhope/poly.c )
s.files += %w( third_party/boringssl/crypto/newhope/precomp.c )
s.files += %w( third_party/boringssl/crypto/newhope/reduce.c )
s.files += %w( third_party/boringssl/crypto/obj/obj.c ) s.files += %w( third_party/boringssl/crypto/obj/obj.c )
s.files += %w( third_party/boringssl/crypto/obj/obj_xref.c ) s.files += %w( third_party/boringssl/crypto/obj/obj_xref.c )
s.files += %w( third_party/boringssl/crypto/pem/pem_all.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_all.c )
@ -906,14 +899,15 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/crypto/pem/pem_pkey.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_pkey.c )
s.files += %w( third_party/boringssl/crypto/pem/pem_x509.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_x509.c )
s.files += %w( third_party/boringssl/crypto/pem/pem_xaux.c ) s.files += %w( third_party/boringssl/crypto/pem/pem_xaux.c )
s.files += %w( third_party/boringssl/crypto/pkcs8/p5_pbe.c )
s.files += %w( third_party/boringssl/crypto/pkcs8/p5_pbev2.c ) s.files += %w( third_party/boringssl/crypto/pkcs8/p5_pbev2.c )
s.files += %w( third_party/boringssl/crypto/pkcs8/p8_pkey.c ) s.files += %w( third_party/boringssl/crypto/pkcs8/p8_pkey.c )
s.files += %w( third_party/boringssl/crypto/pkcs8/pkcs8.c ) s.files += %w( third_party/boringssl/crypto/pkcs8/pkcs8.c )
s.files += %w( third_party/boringssl/crypto/poly1305/poly1305.c ) s.files += %w( third_party/boringssl/crypto/poly1305/poly1305.c )
s.files += %w( third_party/boringssl/crypto/poly1305/poly1305_arm.c ) s.files += %w( third_party/boringssl/crypto/poly1305/poly1305_arm.c )
s.files += %w( third_party/boringssl/crypto/poly1305/poly1305_vec.c ) s.files += %w( third_party/boringssl/crypto/poly1305/poly1305_vec.c )
s.files += %w( third_party/boringssl/crypto/pool/pool.c )
s.files += %w( third_party/boringssl/crypto/rand/deterministic.c ) s.files += %w( third_party/boringssl/crypto/rand/deterministic.c )
s.files += %w( third_party/boringssl/crypto/rand/fuchsia.c )
s.files += %w( third_party/boringssl/crypto/rand/rand.c ) s.files += %w( third_party/boringssl/crypto/rand/rand.c )
s.files += %w( third_party/boringssl/crypto/rand/urandom.c ) s.files += %w( third_party/boringssl/crypto/rand/urandom.c )
s.files += %w( third_party/boringssl/crypto/rand/windows.c ) s.files += %w( third_party/boringssl/crypto/rand/windows.c )
@ -925,6 +919,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/crypto/rsa/rsa.c ) s.files += %w( third_party/boringssl/crypto/rsa/rsa.c )
s.files += %w( third_party/boringssl/crypto/rsa/rsa_asn1.c ) s.files += %w( third_party/boringssl/crypto/rsa/rsa_asn1.c )
s.files += %w( third_party/boringssl/crypto/rsa/rsa_impl.c ) s.files += %w( third_party/boringssl/crypto/rsa/rsa_impl.c )
s.files += %w( third_party/boringssl/crypto/sha/sha1-altivec.c )
s.files += %w( third_party/boringssl/crypto/sha/sha1.c ) s.files += %w( third_party/boringssl/crypto/sha/sha1.c )
s.files += %w( third_party/boringssl/crypto/sha/sha256.c ) s.files += %w( third_party/boringssl/crypto/sha/sha256.c )
s.files += %w( third_party/boringssl/crypto/sha/sha512.c ) s.files += %w( third_party/boringssl/crypto/sha/sha512.c )
@ -933,7 +928,6 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/crypto/thread_none.c ) s.files += %w( third_party/boringssl/crypto/thread_none.c )
s.files += %w( third_party/boringssl/crypto/thread_pthread.c ) s.files += %w( third_party/boringssl/crypto/thread_pthread.c )
s.files += %w( third_party/boringssl/crypto/thread_win.c ) s.files += %w( third_party/boringssl/crypto/thread_win.c )
s.files += %w( third_party/boringssl/crypto/time_support.c )
s.files += %w( third_party/boringssl/crypto/x509/a_digest.c ) s.files += %w( third_party/boringssl/crypto/x509/a_digest.c )
s.files += %w( third_party/boringssl/crypto/x509/a_sign.c ) s.files += %w( third_party/boringssl/crypto/x509/a_sign.c )
s.files += %w( third_party/boringssl/crypto/x509/a_strex.c ) s.files += %w( third_party/boringssl/crypto/x509/a_strex.c )
@ -1017,6 +1011,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/crypto/x509v3/v3_skey.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_skey.c )
s.files += %w( third_party/boringssl/crypto/x509v3/v3_sxnet.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_sxnet.c )
s.files += %w( third_party/boringssl/crypto/x509v3/v3_utl.c ) s.files += %w( third_party/boringssl/crypto/x509v3/v3_utl.c )
s.files += %w( third_party/boringssl/ssl/bio_ssl.c )
s.files += %w( third_party/boringssl/ssl/custom_extensions.c ) s.files += %w( third_party/boringssl/ssl/custom_extensions.c )
s.files += %w( third_party/boringssl/ssl/d1_both.c ) s.files += %w( third_party/boringssl/ssl/d1_both.c )
s.files += %w( third_party/boringssl/ssl/d1_lib.c ) s.files += %w( third_party/boringssl/ssl/d1_lib.c )
@ -1027,7 +1022,6 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/ssl/handshake_client.c ) s.files += %w( third_party/boringssl/ssl/handshake_client.c )
s.files += %w( third_party/boringssl/ssl/handshake_server.c ) s.files += %w( third_party/boringssl/ssl/handshake_server.c )
s.files += %w( third_party/boringssl/ssl/s3_both.c ) s.files += %w( third_party/boringssl/ssl/s3_both.c )
s.files += %w( third_party/boringssl/ssl/s3_enc.c )
s.files += %w( third_party/boringssl/ssl/s3_lib.c ) s.files += %w( third_party/boringssl/ssl/s3_lib.c )
s.files += %w( third_party/boringssl/ssl/s3_pkt.c ) s.files += %w( third_party/boringssl/ssl/s3_pkt.c )
s.files += %w( third_party/boringssl/ssl/ssl_aead_ctx.c ) s.files += %w( third_party/boringssl/ssl/ssl_aead_ctx.c )
@ -1038,9 +1032,12 @@ Gem::Specification.new do |s|
s.files += %w( third_party/boringssl/ssl/ssl_ecdh.c ) s.files += %w( third_party/boringssl/ssl/ssl_ecdh.c )
s.files += %w( third_party/boringssl/ssl/ssl_file.c ) s.files += %w( third_party/boringssl/ssl/ssl_file.c )
s.files += %w( third_party/boringssl/ssl/ssl_lib.c ) s.files += %w( third_party/boringssl/ssl/ssl_lib.c )
s.files += %w( third_party/boringssl/ssl/ssl_rsa.c ) s.files += %w( third_party/boringssl/ssl/ssl_privkey.c )
s.files += %w( third_party/boringssl/ssl/ssl_privkey_cc.cc )
s.files += %w( third_party/boringssl/ssl/ssl_session.c ) s.files += %w( third_party/boringssl/ssl/ssl_session.c )
s.files += %w( third_party/boringssl/ssl/ssl_stat.c ) s.files += %w( third_party/boringssl/ssl/ssl_stat.c )
s.files += %w( third_party/boringssl/ssl/ssl_transcript.c )
s.files += %w( third_party/boringssl/ssl/ssl_x509.c )
s.files += %w( third_party/boringssl/ssl/t1_enc.c ) s.files += %w( third_party/boringssl/ssl/t1_enc.c )
s.files += %w( third_party/boringssl/ssl/t1_lib.c ) s.files += %w( third_party/boringssl/ssl/t1_lib.c )
s.files += %w( third_party/boringssl/ssl/tls13_both.c ) s.files += %w( third_party/boringssl/ssl/tls13_both.c )

@ -52,8 +52,25 @@ class Alarm : private GrpcLibraryCodegen {
alarm_(grpc_alarm_create(cq->cq(), TimePoint<T>(deadline).raw_time(), alarm_(grpc_alarm_create(cq->cq(), TimePoint<T>(deadline).raw_time(),
static_cast<void*>(&tag_))) {} static_cast<void*>(&tag_))) {}
/// Alarms aren't copyable.
Alarm(const Alarm&) = delete;
Alarm& operator=(const Alarm&) = delete;
/// Alarms are movable.
Alarm(Alarm&& rhs) : tag_(rhs.tag_), alarm_(rhs.alarm_) {
rhs.alarm_ = nullptr;
}
Alarm& operator=(Alarm&& rhs) {
tag_ = rhs.tag_;
alarm_ = rhs.alarm_;
rhs.alarm_ = nullptr;
return *this;
}
/// Destroy the given completion queue alarm, cancelling it in the process. /// Destroy the given completion queue alarm, cancelling it in the process.
~Alarm() { grpc_alarm_destroy(alarm_); } ~Alarm() {
if (alarm_ != nullptr) grpc_alarm_destroy(alarm_);
}
/// Cancel a completion queue alarm. Calling this function over an alarm that /// Cancel a completion queue alarm. Calling this function over an alarm that
/// has already fired has no effect. /// has already fired has no effect.
@ -73,7 +90,7 @@ class Alarm : private GrpcLibraryCodegen {
}; };
AlarmEntry tag_; AlarmEntry tag_;
grpc_alarm* const alarm_; // owned grpc_alarm* alarm_; // owned
}; };
} // namespace grpc } // namespace grpc

@ -87,6 +87,28 @@ class ClientAsyncResponseReader final
ClientAsyncResponseReader(call, context, request); ClientAsyncResponseReader(call, context, request);
} }
/// TODO(vjpai): Delete the below constructor
/// PLEASE DO NOT USE THIS CONSTRUCTOR IN NEW CODE
/// This code is only present as a short-term workaround
/// for users that bypassed the code-generator and directly
/// created this struct rather than properly using a stub.
/// This code will not remain a valid public constructor for long.
template <class W>
ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const W& request)
: context_(context),
call_(channel->CreateCall(method, context, cq)),
collection_(std::make_shared<Ops>()) {
collection_->init_buf.SetCollection(collection_);
collection_->init_buf.SendInitialMetadata(
context->send_initial_metadata_, context->initial_metadata_flags());
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(collection_->init_buf.SendMessage(request).ok());
collection_->init_buf.ClientSendClose();
call_.PerformOps(&collection_->init_buf);
}
// always allocated against a call arena, no memory free required // always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) { static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(ClientAsyncResponseReader)); assert(size == sizeof(ClientAsyncResponseReader));
@ -101,9 +123,18 @@ class ClientAsyncResponseReader final
void ReadInitialMetadata(void* tag) { void ReadInitialMetadata(void* tag) {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_); GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_buf_.set_output_tag(tag); Ops& o = ops_;
meta_buf_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_buf_); // TODO(vjpai): Remove the collection_ specialization as soon
// as the public constructor is deleted
if (collection_) {
o = *collection_;
collection_->meta_buf.SetCollection(collection_);
}
o.meta_buf.set_output_tag(tag);
o.meta_buf.RecvInitialMetadata(context_);
call_.PerformOps(&o.meta_buf);
} }
/// See \a ClientAysncResponseReaderInterface::Finish for semantics. /// See \a ClientAysncResponseReaderInterface::Finish for semantics.
@ -112,14 +143,23 @@ class ClientAsyncResponseReader final
/// - the \a ClientContext associated with this call is updated with /// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server. /// possible initial and trailing metadata sent from the server.
void Finish(R* msg, Status* status, void* tag) { void Finish(R* msg, Status* status, void* tag) {
finish_buf_.set_output_tag(tag); Ops& o = ops_;
// TODO(vjpai): Remove the collection_ specialization as soon
// as the public constructor is deleted
if (collection_) {
o = *collection_;
collection_->finish_buf.SetCollection(collection_);
}
o.finish_buf.set_output_tag(tag);
if (!context_->initial_metadata_received_) { if (!context_->initial_metadata_received_) {
finish_buf_.RecvInitialMetadata(context_); o.finish_buf.RecvInitialMetadata(context_);
} }
finish_buf_.RecvMessage(msg); o.finish_buf.RecvMessage(msg);
finish_buf_.AllowNoMessage(); o.finish_buf.AllowNoMessage();
finish_buf_.ClientRecvStatus(context_, status); o.finish_buf.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_buf_); call_.PerformOps(&o.finish_buf);
} }
private: private:
@ -129,25 +169,33 @@ class ClientAsyncResponseReader final
template <class W> template <class W>
ClientAsyncResponseReader(Call call, ClientContext* context, const W& request) ClientAsyncResponseReader(Call call, ClientContext* context, const W& request)
: context_(context), call_(call) { : context_(context), call_(call) {
init_buf_.SendInitialMetadata(context->send_initial_metadata_, ops_.init_buf.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags()); context->initial_metadata_flags());
// TODO(ctiller): don't assert // TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_buf_.SendMessage(request).ok()); GPR_CODEGEN_ASSERT(ops_.init_buf.SendMessage(request).ok());
init_buf_.ClientSendClose(); ops_.init_buf.ClientSendClose();
call_.PerformOps(&init_buf_); call_.PerformOps(&ops_.init_buf);
} }
// disable operator new // disable operator new
static void* operator new(std::size_t size); static void* operator new(std::size_t size);
static void* operator new(std::size_t size, void* p) { return p; } static void* operator new(std::size_t size, void* p) { return p; }
SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, // TODO(vjpai): Remove the reference to CallOpSetCollectionInterface
CallOpClientSendClose> // as soon as the related workaround (public constructor) is deleted
init_buf_; struct Ops : public CallOpSetCollectionInterface {
CallOpSet<CallOpRecvInitialMetadata> meta_buf_; SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>, CallOpClientSendClose>
CallOpClientRecvStatus> init_buf;
finish_buf_; CallOpSet<CallOpRecvInitialMetadata> meta_buf;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
CallOpClientRecvStatus>
finish_buf;
} ops_;
// TODO(vjpai): Remove the collection_ as soon as the related workaround
// (public constructor) is deleted
std::shared_ptr<Ops> collection_;
}; };
/// Async server-side API for handling unary calls, where the single /// Async server-side API for handling unary calls, where the single

@ -544,6 +544,11 @@ class CallOpClientRecvStatus {
grpc_slice error_message_; grpc_slice error_message_;
}; };
/// TODO(vjpai): Remove the existence of CallOpSetCollectionInterface
/// and references to it. This code is deprecated-on-arrival and is
/// only added for users that bypassed the code-generator.
class CallOpSetCollectionInterface {};
/// An abstract collection of call ops, used to generate the /// An abstract collection of call ops, used to generate the
/// grpc_call_op structure to pass down to the lower layers, /// grpc_call_op structure to pass down to the lower layers,
/// and as it is-a CompletionQueueTag, also massages the final /// and as it is-a CompletionQueueTag, also massages the final
@ -554,6 +559,18 @@ class CallOpSetInterface : public CompletionQueueTag {
/// Fills in grpc_op, starting from ops[*nops] and moving /// Fills in grpc_op, starting from ops[*nops] and moving
/// upwards. /// upwards.
virtual void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) = 0; virtual void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) = 0;
/// TODO(vjpai): Remove the SetCollection method and comment. This is only
/// a short-term workaround for users that bypassed the code generator
/// Mark this as belonging to a collection if needed
void SetCollection(std::shared_ptr<CallOpSetCollectionInterface> collection) {
collection_ = collection;
}
protected:
/// TODO(vjpai): Remove the collection_ field once the idea of bypassing the
/// code generator is forbidden. This is already deprecated
std::shared_ptr<CallOpSetCollectionInterface> collection_;
}; };
/// Primary implementaiton of CallOpSetInterface. /// Primary implementaiton of CallOpSetInterface.
@ -593,6 +610,11 @@ class CallOpSet : public CallOpSetInterface,
this->Op5::FinishOp(status); this->Op5::FinishOp(status);
this->Op6::FinishOp(status); this->Op6::FinishOp(status);
*tag = return_tag_; *tag = return_tag_;
// TODO(vjpai): Remove the reference to collection_ once the idea of
// bypassing the code generator is forbidden. It is already deprecated
collection_.reset();
g_core_codegen_interface->grpc_call_unref(call_); g_core_codegen_interface->grpc_call_unref(call_);
return true; return true;
} }

@ -33,7 +33,7 @@
"arguejs": "^0.2.3", "arguejs": "^0.2.3",
"lodash": "^4.15.0", "lodash": "^4.15.0",
"nan": "^2.0.0", "nan": "^2.0.0",
"node-pre-gyp": "^0.6.0", "node-pre-gyp": "^0.6.35",
"protobufjs": "^5.0.0" "protobufjs": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {

@ -106,7 +106,6 @@
<file baseinstalldir="/" name="src/core/lib/support/mpscq.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/mpscq.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/murmur_hash.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/murmur_hash.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/spinlock.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/spinlock.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/string.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_windows.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/string_windows.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/thd_internal.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/thd_internal.h" role="src" />
@ -136,7 +135,6 @@
<file baseinstalldir="/" name="src/core/lib/support/log_windows.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/log_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/mpscq.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/mpscq.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/murmur_hash.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/murmur_hash.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/string.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/string_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_util_windows.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/string_util_windows.c" role="src" />
@ -670,14 +668,14 @@
<file baseinstalldir="/" name="third_party/boringssl/crypto/digest/md32_common.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/digest/md32_common.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/ec/internal.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/ec/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/ec/p256-x86_64-table.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/ec/p256-x86_64-table.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/ec/p256-x86_64.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/evp/internal.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/evp/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/internal.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/modes/internal.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/modes/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/newhope/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/obj/obj_dat.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/obj/obj_dat.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/obj/obj_xref.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pkcs8/internal.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/pkcs8/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/poly1305/internal.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/poly1305/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pool/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/rand/internal.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/rand/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/rsa/internal.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/rsa/internal.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/x509/charmap.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/x509/charmap.h" role="src" />
@ -727,7 +725,6 @@
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/md4.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/md4.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/md5.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/md5.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/mem.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/mem.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/newhope.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/nid.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/nid.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/obj.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/obj.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/obj_mac.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/obj_mac.h" role="src" />
@ -740,6 +737,7 @@
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/pkcs7.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/pkcs7.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/pkcs8.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/pkcs8.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/poly1305.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/poly1305.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/pool.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/rand.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/rand.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/rc4.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/rc4.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/ripemd.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/ripemd.h" role="src" />
@ -752,7 +750,6 @@
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/stack.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/stack.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/stack_macros.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/stack_macros.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/thread.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/thread.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/time_support.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/tls1.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/tls1.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/type_check.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/type_check.h" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/include/openssl/x509.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/include/openssl/x509.h" role="src" />
@ -761,6 +758,7 @@
<file baseinstalldir="/" name="third_party/boringssl/ssl/internal.h" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/internal.h" role="src" />
<file baseinstalldir="/" name="src/boringssl/err_data.c" role="src" /> <file baseinstalldir="/" name="src/boringssl/err_data.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/aes/aes.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/aes/aes.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/aes/key_wrap.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/aes/mode_wrappers.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/aes/mode_wrappers.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/a_bitstr.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/a_bitstr.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/a_bool.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/a_bool.c" role="src" />
@ -792,12 +790,12 @@
<file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/tasn_new.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/tasn_new.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/tasn_typ.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/tasn_typ.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/tasn_utl.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/tasn_utl.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/time_support.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/x_bignum.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/x_bignum.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/x_long.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/x_long.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/base64/base64.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/base64/base64.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/bio/bio.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/bio/bio.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/bio/bio_mem.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/bio/bio_mem.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/bio/buffer.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/bio/connect.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/bio/connect.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/bio/fd.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/bio/fd.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/bio/file.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/bio/file.c" role="src" />
@ -904,12 +902,7 @@
<file baseinstalldir="/" name="third_party/boringssl/crypto/modes/ctr.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/modes/ctr.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/modes/gcm.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/modes/gcm.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/modes/ofb.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/modes/ofb.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/newhope/error_correction.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/modes/polyval.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/newhope/newhope.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/newhope/ntt.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/newhope/poly.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/newhope/precomp.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/newhope/reduce.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/obj/obj.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/obj/obj.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/obj/obj_xref.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/obj/obj_xref.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pem/pem_all.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/pem/pem_all.c" role="src" />
@ -920,14 +913,15 @@
<file baseinstalldir="/" name="third_party/boringssl/crypto/pem/pem_pkey.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/pem/pem_pkey.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pem/pem_x509.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/pem/pem_x509.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pem/pem_xaux.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/pem/pem_xaux.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pkcs8/p5_pbe.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pkcs8/p5_pbev2.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/pkcs8/p5_pbev2.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pkcs8/p8_pkey.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/pkcs8/p8_pkey.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pkcs8/pkcs8.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/pkcs8/pkcs8.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/poly1305/poly1305.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/poly1305/poly1305.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/poly1305/poly1305_arm.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/poly1305/poly1305_arm.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/poly1305/poly1305_vec.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/poly1305/poly1305_vec.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/pool/pool.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/rand/deterministic.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/rand/deterministic.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/rand/fuchsia.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/rand/rand.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/rand/rand.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/rand/urandom.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/rand/urandom.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/rand/windows.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/rand/windows.c" role="src" />
@ -939,6 +933,7 @@
<file baseinstalldir="/" name="third_party/boringssl/crypto/rsa/rsa.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/rsa/rsa.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/rsa/rsa_asn1.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/rsa/rsa_asn1.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/rsa/rsa_impl.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/rsa/rsa_impl.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/sha/sha1-altivec.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/sha/sha1.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/sha/sha1.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/sha/sha256.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/sha/sha256.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/sha/sha512.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/sha/sha512.c" role="src" />
@ -947,7 +942,6 @@
<file baseinstalldir="/" name="third_party/boringssl/crypto/thread_none.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/thread_none.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/thread_pthread.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/thread_pthread.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/thread_win.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/thread_win.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/time_support.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/x509/a_digest.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/x509/a_digest.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/x509/a_sign.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/x509/a_sign.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/x509/a_strex.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/x509/a_strex.c" role="src" />
@ -1031,6 +1025,7 @@
<file baseinstalldir="/" name="third_party/boringssl/crypto/x509v3/v3_skey.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/x509v3/v3_skey.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/x509v3/v3_sxnet.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/x509v3/v3_sxnet.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/x509v3/v3_utl.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/crypto/x509v3/v3_utl.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/bio_ssl.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/custom_extensions.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/custom_extensions.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/d1_both.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/d1_both.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/d1_lib.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/d1_lib.c" role="src" />
@ -1041,7 +1036,6 @@
<file baseinstalldir="/" name="third_party/boringssl/ssl/handshake_client.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/handshake_client.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/handshake_server.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/handshake_server.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/s3_both.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/s3_both.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/s3_enc.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/s3_lib.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/s3_lib.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/s3_pkt.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/s3_pkt.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_aead_ctx.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_aead_ctx.c" role="src" />
@ -1052,9 +1046,12 @@
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_ecdh.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_ecdh.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_file.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_file.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_lib.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_lib.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_rsa.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_privkey.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_privkey_cc.cc" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_session.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_session.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_stat.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_stat.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_transcript.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/ssl_x509.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/t1_enc.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/t1_enc.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/t1_lib.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/t1_lib.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls13_both.c" role="src" /> <file baseinstalldir="/" name="third_party/boringssl/ssl/tls13_both.c" role="src" />

@ -101,9 +101,9 @@ if EXTRA_ENV_COMPILE_ARGS is None:
elif 'win32' in sys.platform: elif 'win32' in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -D_PYTHON_MSVC' EXTRA_ENV_COMPILE_ARGS += ' -D_PYTHON_MSVC'
elif "linux" in sys.platform: elif "linux" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -std=c++11 -std=gnu99 -fvisibility=hidden -fno-wrapv' EXTRA_ENV_COMPILE_ARGS += ' -std=c++11 -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
elif "darwin" in sys.platform: elif "darwin" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv' EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv -fno-exceptions'
if EXTRA_ENV_LINK_ARGS is None: if EXTRA_ENV_LINK_ARGS is None:
EXTRA_ENV_LINK_ARGS = '' EXTRA_ENV_LINK_ARGS = ''
@ -117,7 +117,7 @@ if EXTRA_ENV_LINK_ARGS is None:
' -static-libgcc -static-libstdc++ -mcrtdll={msvcr} ' ' -static-libgcc -static-libstdc++ -mcrtdll={msvcr} '
'-static'.format(msvcr=msvcr)) '-static'.format(msvcr=msvcr))
if "linux" in sys.platform: if "linux" in sys.platform:
EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy' EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy -static-libgcc'
EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS) EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS)
EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS) EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS)

@ -178,42 +178,42 @@ const uint32_t kOpenSSLReasonValues[] = {
0x28340c19, 0x28340c19,
0x283480ac, 0x283480ac,
0x283500ea, 0x283500ea,
0x2c3228ca, 0x2c3229b1,
0x2c32a8d8, 0x2c32a9bf,
0x2c3328ea, 0x2c3329d1,
0x2c33a8fc, 0x2c33a9e3,
0x2c342910, 0x2c3429f7,
0x2c34a922, 0x2c34aa09,
0x2c35293d, 0x2c352a24,
0x2c35a94f, 0x2c35aa36,
0x2c362962, 0x2c362a49,
0x2c36832d, 0x2c36832d,
0x2c37296f, 0x2c372a56,
0x2c37a981, 0x2c37aa68,
0x2c382994, 0x2c382a7b,
0x2c38a9ab, 0x2c38aa92,
0x2c3929b9, 0x2c392aa0,
0x2c39a9c9, 0x2c39aab0,
0x2c3a29db, 0x2c3a2ac2,
0x2c3aa9ef, 0x2c3aaad6,
0x2c3b2a00, 0x2c3b2ae7,
0x2c3baa1f, 0x2c3bab06,
0x2c3c2a33, 0x2c3c2b1a,
0x2c3caa49, 0x2c3cab30,
0x2c3d2a62, 0x2c3d2b49,
0x2c3daa7f, 0x2c3dab66,
0x2c3e2a90, 0x2c3e2b77,
0x2c3eaa9e, 0x2c3eab85,
0x2c3f2ab6, 0x2c3f2b9d,
0x2c3faace, 0x2c3fabb5,
0x2c402adb, 0x2c402bc2,
0x2c4090e7, 0x2c4090e7,
0x2c412aec, 0x2c412bd3,
0x2c41aaff, 0x2c41abe6,
0x2c4210c0, 0x2c4210c0,
0x2c42ab10, 0x2c42abf7,
0x2c430720, 0x2c430720,
0x2c43aa11, 0x2c43aaf8,
0x30320000, 0x30320000,
0x30328015, 0x30328015,
0x3033001f, 0x3033001f,
@ -366,180 +366,189 @@ const uint32_t kOpenSSLReasonValues[] = {
0x403b9861, 0x403b9861,
0x403c0064, 0x403c0064,
0x403c8083, 0x403c8083,
0x403d18aa, 0x403d18c1,
0x403d98c0, 0x403d98d7,
0x403e18cf, 0x403e18e6,
0x403e98e2, 0x403e98f9,
0x403f18fc, 0x403f1913,
0x403f990a, 0x403f9921,
0x4040191f, 0x40401936,
0x40409933, 0x4040994a,
0x40411950, 0x40411967,
0x4041996b, 0x40419982,
0x40421984, 0x4042199b,
0x40429997, 0x404299ae,
0x404319ab, 0x404319c2,
0x404399c3, 0x404399da,
0x404419da, 0x404419f1,
0x404480ac, 0x404480ac,
0x404519ef, 0x40451a06,
0x40459a01, 0x40459a18,
0x40461a25, 0x40461a3c,
0x40469a45, 0x40469a5c,
0x40471a53, 0x40471a6a,
0x40479a7a, 0x40479a91,
0x40481ab7, 0x40481ace,
0x40489ad0, 0x40489ae7,
0x40491ae7, 0x40491afe,
0x40499b01, 0x40499b18,
0x404a1b18, 0x404a1b2f,
0x404a9b36, 0x404a9b4d,
0x404b1b4e, 0x404b1b65,
0x404b9b65, 0x404b9b7c,
0x404c1b7b, 0x404c1b92,
0x404c9b8d, 0x404c9ba4,
0x404d1bae, 0x404d1bc5,
0x404d9bd0, 0x404d9be7,
0x404e1be4, 0x404e1bfb,
0x404e9bf1, 0x404e9c08,
0x404f1c1e, 0x404f1c35,
0x404f9c47, 0x404f9c5e,
0x40501c71, 0x40501c99,
0x40509c85, 0x40509cad,
0x40511ca0, 0x40511cc8,
0x40519cb0, 0x40519cd8,
0x40521cc7, 0x40521cef,
0x40529ceb, 0x40529d13,
0x40531d03, 0x40531d2b,
0x40539d16, 0x40539d3e,
0x40541d2b, 0x40541d53,
0x40549d4e, 0x40549d76,
0x40551d5c, 0x40551d84,
0x40559d79, 0x40559da1,
0x40561d86, 0x40561dae,
0x40569d9f, 0x40569dc7,
0x40571db7, 0x40571ddf,
0x40579dca, 0x40579df2,
0x40581ddf, 0x40581e07,
0x40589e06, 0x40589e2e,
0x40591e35, 0x40591e5d,
0x40599e62, 0x40599e8a,
0x405a1e76, 0x405a1e9e,
0x405a9e86, 0x405a9eae,
0x405b1e9e, 0x405b1ec6,
0x405b9eaf, 0x405b9ed7,
0x405c1ec2, 0x405c1eea,
0x405c9ed3, 0x405c9f0b,
0x405d1ee0, 0x405d1f18,
0x405d9ef7, 0x405d9f2f,
0x405e1f17, 0x405e1f6d,
0x405e8a95, 0x405e8a95,
0x405f1f38, 0x405f1f8e,
0x405f9f45, 0x405f9f9b,
0x40601f53, 0x40601fa9,
0x40609f75, 0x40609fcb,
0x40611f9d, 0x4061200f,
0x40619fb2, 0x4061a047,
0x40621fc9, 0x4062205e,
0x40629fda, 0x4062a06f,
0x40631feb, 0x40632080,
0x4063a000, 0x4063a095,
0x40642017, 0x406420ac,
0x4064a043, 0x4064a0d8,
0x4065205e, 0x406520f3,
0x4065a075, 0x4065a10a,
0x4066208d, 0x40662122,
0x4066a0b7, 0x4066a14c,
0x406720e2, 0x40672177,
0x4067a103, 0x4067a198,
0x40682116, 0x406821ab,
0x4068a137, 0x4068a1cc,
0x40692169, 0x406921fe,
0x4069a197, 0x4069a22c,
0x406a21b8, 0x406a224d,
0x406aa1d8, 0x406aa26d,
0x406b2360, 0x406b23f5,
0x406ba383, 0x406ba418,
0x406c2399, 0x406c242e,
0x406ca5c5, 0x406ca690,
0x406d25f4, 0x406d26bf,
0x406da61c, 0x406da6e7,
0x406e264a, 0x406e2715,
0x406ea662, 0x406ea749,
0x406f2681, 0x406f2768,
0x406fa696, 0x406fa77d,
0x407026a9, 0x40702790,
0x4070a6c6, 0x4070a7ad,
0x40710800, 0x40710800,
0x4071a6d8, 0x4071a7bf,
0x407226eb, 0x407227d2,
0x4072a704, 0x4072a7eb,
0x4073271c, 0x40732803,
0x4073936d, 0x4073936d,
0x40742730, 0x40742817,
0x4074a74a, 0x4074a831,
0x4075275b, 0x40752842,
0x4075a76f, 0x4075a856,
0x4076277d, 0x40762864,
0x407691aa, 0x407691aa,
0x407727a2, 0x40772889,
0x4077a7c4, 0x4077a8ab,
0x407827df, 0x407828c6,
0x4078a818, 0x4078a8ff,
0x4079282f, 0x40792916,
0x4079a845, 0x4079a92c,
0x407a2851, 0x407a2938,
0x407aa864, 0x407aa94b,
0x407b2879, 0x407b2960,
0x407ba88b, 0x407ba972,
0x407c28a0, 0x407c2987,
0x407ca8a9, 0x407ca990,
0x407d2152, 0x407d21e7,
0x407d9c57, 0x407d9c6e,
0x407e27f4, 0x407e28db,
0x407e9e16, 0x407e9e3e,
0x407f1a67, 0x407f1a7e,
0x407f9887, 0x407f9887,
0x40801c2e, 0x40801c45,
0x40809a8f, 0x40809aa6,
0x40811cd9, 0x40811d01,
0x40819c08, 0x40819c1f,
0x40822635, 0x40822700,
0x4082986d, 0x4082986d,
0x40831df1, 0x40831e19,
0x4083a028, 0x4083a0bd,
0x40841aa3, 0x40841aba,
0x40849e4e, 0x40849e76,
0x41f4228b, 0x40851efb,
0x41f9231d, 0x40859ff3,
0x41fe2210, 0x40861f4f,
0x41fea3ec, 0x40869c88,
0x41ff24dd, 0x4087272d,
0x420322a4, 0x4087a024,
0x420822c6, 0x408818aa,
0x4208a302, 0x41f42320,
0x420921f4, 0x41f923b2,
0x4209a33c, 0x41fe22a5,
0x420a224b, 0x41fea481,
0x420aa22b, 0x41ff2572,
0x420b226b, 0x42032339,
0x420ba2e4, 0x4208235b,
0x420c24f9, 0x4208a397,
0x420ca3b9, 0x42092289,
0x420d23d3, 0x4209a3d1,
0x420da40a, 0x420a22e0,
0x42122424, 0x420aa2c0,
0x421724c0, 0x420b2300,
0x4217a466, 0x420ba379,
0x421c2488, 0x420c258e,
0x421f2443, 0x420ca44e,
0x42212510, 0x420d2468,
0x422624a3, 0x420da49f,
0x422b25a9, 0x421224b9,
0x422ba572, 0x42172555,
0x422c2591, 0x4217a4fb,
0x422ca54c, 0x421c251d,
0x422d252b, 0x421f24d8,
0x422125a5,
0x42262538,
0x422b2674,
0x422ba622,
0x422c265c,
0x422ca5e1,
0x422d25c0,
0x422da641,
0x422e2607,
0x4432072b, 0x4432072b,
0x4432873a, 0x4432873a,
0x44330746, 0x44330746,
@ -582,69 +591,69 @@ const uint32_t kOpenSSLReasonValues[] = {
0x4c3d136d, 0x4c3d136d,
0x4c3d937c, 0x4c3d937c,
0x4c3e1389, 0x4c3e1389,
0x50322b22, 0x50322c09,
0x5032ab31, 0x5032ac18,
0x50332b3c, 0x50332c23,
0x5033ab4c, 0x5033ac33,
0x50342b65, 0x50342c4c,
0x5034ab7f, 0x5034ac66,
0x50352b8d, 0x50352c74,
0x5035aba3, 0x5035ac8a,
0x50362bb5, 0x50362c9c,
0x5036abcb, 0x5036acb2,
0x50372be4, 0x50372ccb,
0x5037abf7, 0x5037acde,
0x50382c0f, 0x50382cf6,
0x5038ac20, 0x5038ad07,
0x50392c35, 0x50392d1c,
0x5039ac49, 0x5039ad30,
0x503a2c69, 0x503a2d50,
0x503aac7f, 0x503aad66,
0x503b2c97, 0x503b2d7e,
0x503baca9, 0x503bad90,
0x503c2cc5, 0x503c2dac,
0x503cacdc, 0x503cadc3,
0x503d2cf5, 0x503d2ddc,
0x503dad0b, 0x503dadf2,
0x503e2d18, 0x503e2dff,
0x503ead2e, 0x503eae15,
0x503f2d40, 0x503f2e27,
0x503f8382, 0x503f8382,
0x50402d53, 0x50402e3a,
0x5040ad63, 0x5040ae4a,
0x50412d7d, 0x50412e64,
0x5041ad8c, 0x5041ae73,
0x50422da6, 0x50422e8d,
0x5042adc3, 0x5042aeaa,
0x50432dd3, 0x50432eba,
0x5043ade3, 0x5043aeca,
0x50442df2, 0x50442ed9,
0x5044843f, 0x5044843f,
0x50452e06, 0x50452eed,
0x5045ae24, 0x5045af0b,
0x50462e37, 0x50462f1e,
0x5046ae4d, 0x5046af34,
0x50472e5f, 0x50472f46,
0x5047ae74, 0x5047af5b,
0x50482e9a, 0x50482f81,
0x5048aea8, 0x5048af8f,
0x50492ebb, 0x50492fa2,
0x5049aed0, 0x5049afb7,
0x504a2ee6, 0x504a2fcd,
0x504aaef6, 0x504aafdd,
0x504b2f16, 0x504b2ffd,
0x504baf29, 0x504bb010,
0x504c2f4c, 0x504c3033,
0x504caf7a, 0x504cb061,
0x504d2f8c, 0x504d3073,
0x504dafa9, 0x504db090,
0x504e2fc4, 0x504e30ab,
0x504eafe0, 0x504eb0c7,
0x504f2ff2, 0x504f30d9,
0x504fb009, 0x504fb0f0,
0x50503018, 0x505030ff,
0x505086ef, 0x505086ef,
0x5051302b, 0x50513112,
0x58320ec9, 0x58320ec9,
0x68320e8b, 0x68320e8b,
0x68328c25, 0x68328c25,
@ -1007,6 +1016,7 @@ const char kOpenSSLReasonStringData[] =
"BIO_NOT_SET\0" "BIO_NOT_SET\0"
"BLOCK_CIPHER_PAD_IS_WRONG\0" "BLOCK_CIPHER_PAD_IS_WRONG\0"
"BUFFERED_MESSAGES_ON_CIPHER_CHANGE\0" "BUFFERED_MESSAGES_ON_CIPHER_CHANGE\0"
"CANNOT_PARSE_LEAF_CERT\0"
"CA_DN_LENGTH_MISMATCH\0" "CA_DN_LENGTH_MISMATCH\0"
"CA_DN_TOO_LONG\0" "CA_DN_TOO_LONG\0"
"CCS_RECEIVED_EARLY\0" "CCS_RECEIVED_EARLY\0"
@ -1050,6 +1060,7 @@ const char kOpenSSLReasonStringData[] =
"INVALID_COMPRESSION_LIST\0" "INVALID_COMPRESSION_LIST\0"
"INVALID_MESSAGE\0" "INVALID_MESSAGE\0"
"INVALID_OUTER_RECORD_TYPE\0" "INVALID_OUTER_RECORD_TYPE\0"
"INVALID_SCT_LIST\0"
"INVALID_SSL_SESSION\0" "INVALID_SSL_SESSION\0"
"INVALID_TICKET_KEYS_LENGTH\0" "INVALID_TICKET_KEYS_LENGTH\0"
"LENGTH_MISMATCH\0" "LENGTH_MISMATCH\0"
@ -1079,15 +1090,19 @@ const char kOpenSSLReasonStringData[] =
"NO_RENEGOTIATION\0" "NO_RENEGOTIATION\0"
"NO_REQUIRED_DIGEST\0" "NO_REQUIRED_DIGEST\0"
"NO_SHARED_CIPHER\0" "NO_SHARED_CIPHER\0"
"NO_SHARED_GROUP\0"
"NULL_SSL_CTX\0" "NULL_SSL_CTX\0"
"NULL_SSL_METHOD_PASSED\0" "NULL_SSL_METHOD_PASSED\0"
"OLD_SESSION_CIPHER_NOT_RETURNED\0" "OLD_SESSION_CIPHER_NOT_RETURNED\0"
"OLD_SESSION_PRF_HASH_MISMATCH\0"
"OLD_SESSION_VERSION_NOT_RETURNED\0" "OLD_SESSION_VERSION_NOT_RETURNED\0"
"PARSE_TLSEXT\0" "PARSE_TLSEXT\0"
"PATH_TOO_LONG\0" "PATH_TOO_LONG\0"
"PEER_DID_NOT_RETURN_A_CERTIFICATE\0" "PEER_DID_NOT_RETURN_A_CERTIFICATE\0"
"PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0" "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0"
"PRE_SHARED_KEY_MUST_BE_LAST\0"
"PROTOCOL_IS_SHUTDOWN\0" "PROTOCOL_IS_SHUTDOWN\0"
"PSK_IDENTITY_BINDER_COUNT_MISMATCH\0"
"PSK_IDENTITY_NOT_FOUND\0" "PSK_IDENTITY_NOT_FOUND\0"
"PSK_NO_CLIENT_CB\0" "PSK_NO_CLIENT_CB\0"
"PSK_NO_SERVER_CB\0" "PSK_NO_SERVER_CB\0"
@ -1139,7 +1154,9 @@ const char kOpenSSLReasonStringData[] =
"TLSV1_ALERT_USER_CANCELLED\0" "TLSV1_ALERT_USER_CANCELLED\0"
"TLSV1_BAD_CERTIFICATE_HASH_VALUE\0" "TLSV1_BAD_CERTIFICATE_HASH_VALUE\0"
"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0" "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0"
"TLSV1_CERTIFICATE_REQUIRED\0"
"TLSV1_CERTIFICATE_UNOBTAINABLE\0" "TLSV1_CERTIFICATE_UNOBTAINABLE\0"
"TLSV1_UNKNOWN_PSK_IDENTITY\0"
"TLSV1_UNRECOGNIZED_NAME\0" "TLSV1_UNRECOGNIZED_NAME\0"
"TLSV1_UNSUPPORTED_EXTENSION\0" "TLSV1_UNSUPPORTED_EXTENSION\0"
"TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0" "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0"
@ -1147,6 +1164,7 @@ const char kOpenSSLReasonStringData[] =
"TOO_MANY_EMPTY_FRAGMENTS\0" "TOO_MANY_EMPTY_FRAGMENTS\0"
"TOO_MANY_KEY_UPDATES\0" "TOO_MANY_KEY_UPDATES\0"
"TOO_MANY_WARNING_ALERTS\0" "TOO_MANY_WARNING_ALERTS\0"
"TOO_MUCH_SKIPPED_EARLY_DATA\0"
"UNABLE_TO_FIND_ECDH_PARAMETERS\0" "UNABLE_TO_FIND_ECDH_PARAMETERS\0"
"UNEXPECTED_EXTENSION\0" "UNEXPECTED_EXTENSION\0"
"UNEXPECTED_MESSAGE\0" "UNEXPECTED_MESSAGE\0"

@ -52,14 +52,16 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
vars["input_type_id"] = MessageIdentifierName(input_type->full_name()); vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
vars["output_type_id"] = MessageIdentifierName(output_type->full_name()); vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
out->Print(GetPHPComments(method, " //").c_str()); out->Print("/**\n");
out->Print(GetPHPComments(method, " *").c_str());
if (method->client_streaming()) { if (method->client_streaming()) {
out->Print(vars, out->Print(vars,
" // @param array $$metadata metadata\n" " * @param array $$metadata metadata\n"
" // @param array $$options call options\n" " * @param array $$options call options\n */\n"
"public function $name$($$metadata = [], " "public function $name$($$metadata = [], "
"$$options = []) {\n"); "$$options = []) {\n");
out->Indent(); out->Indent();
out->Indent();
if (method->server_streaming()) { if (method->server_streaming()) {
out->Print("return $$this->_bidiRequest("); out->Print("return $$this->_bidiRequest(");
} else { } else {
@ -71,12 +73,13 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
"$$metadata, $$options);\n"); "$$metadata, $$options);\n");
} else { } else {
out->Print(vars, out->Print(vars,
" // @param \\$input_type_id$ $$argument input argument\n" " * @param \\$input_type_id$ $$argument input argument\n"
" // @param array $$metadata metadata\n" " * @param array $$metadata metadata\n"
" // @param array $$options call options\n" " * @param array $$options call options\n */\n"
"public function $name$(\\$input_type_id$ $$argument,\n" "public function $name$(\\$input_type_id$ $$argument,\n"
" $$metadata = [], $$options = []) {\n"); " $$metadata = [], $$options = []) {\n");
out->Indent(); out->Indent();
out->Indent();
if (method->server_streaming()) { if (method->server_streaming()) {
out->Print("return $$this->_serverStreamRequest("); out->Print("return $$this->_serverStreamRequest(");
} else { } else {
@ -89,26 +92,32 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
"$$metadata, $$options);\n"); "$$metadata, $$options);\n");
} }
out->Outdent(); out->Outdent();
out->Outdent();
out->Print("}\n\n"); out->Print("}\n\n");
} }
// Prints out the service descriptor object // Prints out the service descriptor object
void PrintService(const ServiceDescriptor *service, Printer *out) { void PrintService(const ServiceDescriptor *service, Printer *out) {
map<grpc::string, grpc::string> vars; map<grpc::string, grpc::string> vars;
out->Print(GetPHPComments(service, "//").c_str()); out->Print("/**\n");
out->Print(GetPHPComments(service, " *").c_str());
out->Print(" */\n");
vars["name"] = service->name(); vars["name"] = service->name();
out->Print(vars, "class $name$Client extends \\Grpc\\BaseStub {\n\n"); out->Print(vars, "class $name$Client extends \\Grpc\\BaseStub {\n\n");
out->Indent(); out->Indent();
out->Indent();
out->Print( out->Print(
" // @param string $$hostname hostname\n" "/**\n * @param string $$hostname hostname\n"
" // @param array $$opts channel options\n" " * @param array $$opts channel options\n"
" // @param \\Grpc\\Channel $$channel (optional) re-use channel " " * @param \\Grpc\\Channel $$channel (optional) re-use channel "
"object\n" "object\n */\n"
"public function __construct($$hostname, $$opts, " "public function __construct($$hostname, $$opts, "
"$$channel = null) {\n"); "$$channel = null) {\n");
out->Indent(); out->Indent();
out->Indent();
out->Print("parent::__construct($$hostname, $$opts, $$channel);\n"); out->Print("parent::__construct($$hostname, $$opts, $$channel);\n");
out->Outdent(); out->Outdent();
out->Outdent();
out->Print("}\n\n"); out->Print("}\n\n");
for (int i = 0; i < service->method_count(); i++) { for (int i = 0; i < service->method_count(); i++) {
grpc::string method_name = grpc::string method_name =
@ -116,7 +125,8 @@ void PrintService(const ServiceDescriptor *service, Printer *out) {
PrintMethod(service->method(i), out); PrintMethod(service->method(i), out);
} }
out->Outdent(); out->Outdent();
out->Print("}\n\n"); out->Outdent();
out->Print("}\n");
} }
} }
@ -138,13 +148,9 @@ grpc::string GenerateFile(const FileDescriptor *file,
map<grpc::string, grpc::string> vars; map<grpc::string, grpc::string> vars;
vars["package"] = MessageIdentifierName(file->package()); vars["package"] = MessageIdentifierName(file->package());
out.Print(vars, "namespace $package$ {\n\n"); out.Print(vars, "namespace $package$;\n\n");
out.Indent();
PrintService(service, &out); PrintService(service, &out);
out.Outdent();
out.Print("}\n");
} }
return output; return output;
} }

@ -39,12 +39,24 @@ inline grpc::string GetPHPServiceFilename(
return oss.str() + "/" + service->name() + "Client.php"; return oss.str() + "/" + service->name() + "Client.php";
} }
// ReplaceAll replaces all instances of search with replace in s.
inline grpc::string ReplaceAll(grpc::string s, const grpc::string &search,
const grpc::string &replace) {
size_t pos = 0;
while ((pos = s.find(search, pos)) != grpc::string::npos) {
s.replace(pos, search.length(), replace);
pos += replace.length();
}
return s;
}
// Get leading or trailing comments in a string. Comment lines start with "// ". // Get leading or trailing comments in a string. Comment lines start with "// ".
// Leading detached comments are put in in front of leading comments. // Leading detached comments are put in in front of leading comments.
template <typename DescriptorType> template <typename DescriptorType>
inline grpc::string GetPHPComments(const DescriptorType *desc, inline grpc::string GetPHPComments(const DescriptorType *desc,
grpc::string prefix) { grpc::string prefix) {
return grpc_generator::GetPrefixedComments(desc, true, prefix); return ReplaceAll(grpc_generator::GetPrefixedComments(desc, true, prefix),
"*/", "&#42;/");
} }
} // namespace grpc_php_generator } // namespace grpc_php_generator

@ -178,8 +178,8 @@ typedef struct client_channel_channel_data {
grpc_slice_hash_table *method_params_table; grpc_slice_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */ /** incoming resolver result - set by resolver.next() */
grpc_channel_args *resolver_result; grpc_channel_args *resolver_result;
/** a list of closures that are all waiting for config to come in */ /** a list of closures that are all waiting for resolver result to come in */
grpc_closure_list waiting_for_config_closures; grpc_closure_list waiting_for_resolver_result_closures;
/** resolver callback */ /** resolver callback */
grpc_closure on_resolver_result_changed; grpc_closure on_resolver_result_changed;
/** connectivity state being tracked */ /** connectivity state being tracked */
@ -342,49 +342,15 @@ static void parse_retry_throttle_params(const grpc_json *field, void *arg) {
} }
} }
// Wrap a closure associated with \a lb_policy. The associated callback (\a
// wrapped_on_pick_closure_cb) is responsible for unref'ing \a lb_policy after
// scheduling \a wrapped_closure.
typedef struct wrapped_on_pick_closure_arg {
/* the closure instance using this struct as argument */
grpc_closure wrapper_closure;
/* the original closure. Usually a on_complete/notify cb for pick() and ping()
* calls against the internal RR instance, respectively. */
grpc_closure *wrapped_closure;
/* The policy instance related to the closure */
grpc_lb_policy *lb_policy;
} wrapped_on_pick_closure_arg;
// Invoke \a arg->wrapped_closure, unref \a arg->lb_policy and free \a arg.
static void wrapped_on_pick_closure_cb(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
wrapped_on_pick_closure_arg *wc_arg = arg;
GPR_ASSERT(wc_arg != NULL);
GPR_ASSERT(wc_arg->wrapped_closure != NULL);
GPR_ASSERT(wc_arg->lb_policy != NULL);
GRPC_CLOSURE_RUN(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error));
GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->lb_policy, "pick_subchannel_wrapping");
gpr_free(wc_arg);
}
static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx, static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
void *arg, grpc_error *error) { void *arg, grpc_error *error) {
channel_data *chand = arg; channel_data *chand = arg;
// Extract the following fields from the resolver result, if non-NULL.
char *lb_policy_name = NULL; char *lb_policy_name = NULL;
grpc_lb_policy *lb_policy = NULL; grpc_lb_policy *new_lb_policy = NULL;
grpc_lb_policy *old_lb_policy = NULL;
grpc_slice_hash_table *method_params_table = NULL;
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
bool exit_idle = false;
grpc_error *state_error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy");
char *service_config_json = NULL; char *service_config_json = NULL;
service_config_parsing_state parsing_state; grpc_server_retry_throttle_data *retry_throttle_data = NULL;
memset(&parsing_state, 0, sizeof(parsing_state)); grpc_slice_hash_table *method_params_table = NULL;
bool lb_policy_updated = false;
if (chand->resolver_result != NULL) { if (chand->resolver_result != NULL) {
// Find LB policy name. // Find LB policy name.
const grpc_arg *channel_arg = const grpc_arg *channel_arg =
@ -419,32 +385,29 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
// Use pick_first if nothing was specified and we didn't select grpclb // Use pick_first if nothing was specified and we didn't select grpclb
// above. // above.
if (lb_policy_name == NULL) lb_policy_name = "pick_first"; if (lb_policy_name == NULL) lb_policy_name = "pick_first";
// Instantiate LB policy.
grpc_lb_policy_args lb_policy_args; grpc_lb_policy_args lb_policy_args;
lb_policy_args.args = chand->resolver_result; lb_policy_args.args = chand->resolver_result;
lb_policy_args.client_channel_factory = chand->client_channel_factory; lb_policy_args.client_channel_factory = chand->client_channel_factory;
lb_policy_args.combiner = chand->combiner; lb_policy_args.combiner = chand->combiner;
// Check to see if we're already using the right LB policy.
// Note: It's safe to use chand->info_lb_policy_name here without
// taking a lock on chand->info_mu, because this function is the
// only thing that modifies its value, and it can only be invoked
// once at any given time.
const bool lb_policy_type_changed = const bool lb_policy_type_changed =
(chand->info_lb_policy_name == NULL) || chand->info_lb_policy_name == NULL ||
(strcmp(chand->info_lb_policy_name, lb_policy_name) != 0); strcmp(chand->info_lb_policy_name, lb_policy_name) != 0;
if (chand->lb_policy != NULL && !lb_policy_type_changed) { if (chand->lb_policy != NULL && !lb_policy_type_changed) {
// update // Continue using the same LB policy. Update with new addresses.
lb_policy_updated = true;
grpc_lb_policy_update_locked(exec_ctx, chand->lb_policy, &lb_policy_args); grpc_lb_policy_update_locked(exec_ctx, chand->lb_policy, &lb_policy_args);
} else { } else {
lb_policy = // Instantiate new LB policy.
new_lb_policy =
grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args); grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
if (lb_policy != NULL) { if (new_lb_policy == NULL) {
GRPC_LB_POLICY_REF(lb_policy, "config_change"); gpr_log(GPR_ERROR, "could not create LB policy \"%s\"", lb_policy_name);
GRPC_ERROR_UNREF(state_error);
state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
&state_error);
old_lb_policy = chand->lb_policy;
chand->lb_policy = lb_policy;
} }
} }
// Find service config. // Find service config.
channel_arg = channel_arg =
grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG); grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
@ -461,12 +424,14 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
grpc_uri *uri = grpc_uri *uri =
grpc_uri_parse(exec_ctx, channel_arg->value.string, true); grpc_uri_parse(exec_ctx, channel_arg->value.string, true);
GPR_ASSERT(uri->path[0] != '\0'); GPR_ASSERT(uri->path[0] != '\0');
service_config_parsing_state parsing_state;
memset(&parsing_state, 0, sizeof(parsing_state));
parsing_state.server_name = parsing_state.server_name =
uri->path[0] == '/' ? uri->path + 1 : uri->path; uri->path[0] == '/' ? uri->path + 1 : uri->path;
grpc_service_config_parse_global_params( grpc_service_config_parse_global_params(
service_config, parse_retry_throttle_params, &parsing_state); service_config, parse_retry_throttle_params, &parsing_state);
parsing_state.server_name = NULL;
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
retry_throttle_data = parsing_state.retry_throttle_data;
method_params_table = grpc_service_config_create_method_config_table( method_params_table = grpc_service_config_create_method_config_table(
exec_ctx, service_config, method_parameters_create_from_json, exec_ctx, service_config, method_parameters_create_from_json,
method_parameters_free); method_parameters_free);
@ -480,12 +445,11 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
grpc_channel_args_destroy(exec_ctx, chand->resolver_result); grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
chand->resolver_result = NULL; chand->resolver_result = NULL;
} }
// Now swap out fields in chand. Note that the new values may still
if (lb_policy != NULL) { // be NULL if (e.g.) the resolver failed to return results or the
grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties, // results did not contain the necessary data.
chand->interested_parties); //
} // First, swap out the data used by cc_get_channel_info().
gpr_mu_lock(&chand->info_mu); gpr_mu_lock(&chand->info_mu);
if (lb_policy_name != NULL) { if (lb_policy_name != NULL) {
gpr_free(chand->info_lb_policy_name); gpr_free(chand->info_lb_policy_name);
@ -496,75 +460,77 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
chand->info_service_config_json = service_config_json; chand->info_service_config_json = service_config_json;
} }
gpr_mu_unlock(&chand->info_mu); gpr_mu_unlock(&chand->info_mu);
// Swap out the retry throttle data.
if (chand->retry_throttle_data != NULL) { if (chand->retry_throttle_data != NULL) {
grpc_server_retry_throttle_data_unref(chand->retry_throttle_data); grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
} }
chand->retry_throttle_data = parsing_state.retry_throttle_data; chand->retry_throttle_data = retry_throttle_data;
// Swap out the method params table.
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table); grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
} }
chand->method_params_table = method_params_table; chand->method_params_table = method_params_table;
if (lb_policy != NULL) { // If we have a new LB policy or are shutting down (in which case
GRPC_CLOSURE_LIST_SCHED(exec_ctx, &chand->waiting_for_config_closures); // new_lb_policy will be NULL), swap out the LB policy, unreffing the
} else if (chand->resolver == NULL /* disconnected */) { // old one and removing its fds from chand->interested_parties.
grpc_closure_list_fail_all(&chand->waiting_for_config_closures, // Note that we do NOT do this if either (a) we updated the existing
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( // LB policy above or (b) we failed to create the new LB policy (in
"Channel disconnected", &error, 1)); // which case we want to continue using the most recent one we had).
GRPC_CLOSURE_LIST_SCHED(exec_ctx, &chand->waiting_for_config_closures); if (new_lb_policy != NULL || error != GRPC_ERROR_NONE ||
} chand->resolver == NULL) {
if (!lb_policy_updated && lb_policy != NULL && if (chand->lb_policy != NULL) {
chand->exit_idle_when_lb_policy_arrives) { grpc_pollset_set_del_pollset_set(exec_ctx,
GRPC_LB_POLICY_REF(lb_policy, "exit_idle"); chand->lb_policy->interested_parties,
exit_idle = true; chand->interested_parties);
chand->exit_idle_when_lb_policy_arrives = false; GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
}
if (error == GRPC_ERROR_NONE && chand->resolver) {
if (!lb_policy_updated) {
set_channel_connectivity_state_locked(exec_ctx, chand, state,
GRPC_ERROR_REF(state_error),
"new_lb+resolver");
if (lb_policy != NULL) {
watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
}
} }
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); chand->lb_policy = new_lb_policy;
grpc_resolver_next_locked(exec_ctx, chand->resolver, }
&chand->resolver_result, // Now that we've swapped out the relevant fields of chand, check for
&chand->on_resolver_result_changed); // error or shutdown.
} else { if (error != GRPC_ERROR_NONE || chand->resolver == NULL) {
if (chand->resolver != NULL) { if (chand->resolver != NULL) {
grpc_resolver_shutdown_locked(exec_ctx, chand->resolver); grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL; chand->resolver = NULL;
} }
grpc_error *refs[] = {error, state_error};
set_channel_connectivity_state_locked( set_channel_connectivity_state_locked(
exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN, exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Got config after disconnection", refs, GPR_ARRAY_SIZE(refs)), "Got resolver result after disconnection", &error, 1),
"resolver_gone"); "resolver_gone");
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
grpc_closure_list_fail_all(&chand->waiting_for_resolver_result_closures,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Channel disconnected", &error, 1));
GRPC_CLOSURE_LIST_SCHED(exec_ctx,
&chand->waiting_for_resolver_result_closures);
} else { // Not shutting down.
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
grpc_error *state_error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy");
if (new_lb_policy != NULL) {
GRPC_ERROR_UNREF(state_error);
state = grpc_lb_policy_check_connectivity_locked(exec_ctx, new_lb_policy,
&state_error);
grpc_pollset_set_add_pollset_set(exec_ctx,
new_lb_policy->interested_parties,
chand->interested_parties);
GRPC_CLOSURE_LIST_SCHED(exec_ctx,
&chand->waiting_for_resolver_result_closures);
if (chand->exit_idle_when_lb_policy_arrives) {
grpc_lb_policy_exit_idle_locked(exec_ctx, new_lb_policy);
chand->exit_idle_when_lb_policy_arrives = false;
}
watch_lb_policy_locked(exec_ctx, chand, new_lb_policy, state);
}
set_channel_connectivity_state_locked(
exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
grpc_resolver_next_locked(exec_ctx, chand->resolver,
&chand->resolver_result,
&chand->on_resolver_result_changed);
GRPC_ERROR_UNREF(state_error);
} }
if (!lb_policy_updated && lb_policy != NULL && exit_idle) {
grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
}
if (old_lb_policy != NULL) {
grpc_pollset_set_del_pollset_set(
exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
old_lb_policy = NULL;
}
if (!lb_policy_updated && lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
}
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
GRPC_ERROR_UNREF(state_error);
} }
static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg, static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
@ -602,9 +568,10 @@ static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL; chand->resolver = NULL;
if (!chand->started_resolving) { if (!chand->started_resolving) {
grpc_closure_list_fail_all(&chand->waiting_for_config_closures, grpc_closure_list_fail_all(&chand->waiting_for_resolver_result_closures,
GRPC_ERROR_REF(op->disconnect_with_error)); GRPC_ERROR_REF(op->disconnect_with_error));
GRPC_CLOSURE_LIST_SCHED(exec_ctx, &chand->waiting_for_config_closures); GRPC_CLOSURE_LIST_SCHED(exec_ctx,
&chand->waiting_for_resolver_result_closures);
} }
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
grpc_pollset_set_del_pollset_set(exec_ctx, grpc_pollset_set_del_pollset_set(exec_ctx,
@ -770,6 +737,16 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
* PER-CALL FUNCTIONS * PER-CALL FUNCTIONS
*/ */
// Max number of batches that can be pending on a call at any given
// time. This includes:
// recv_initial_metadata
// send_initial_metadata
// recv_message
// send_message
// recv_trailing_metadata
// send_trailing_metadata
#define MAX_WAITING_BATCHES 6
/** Call data. Holds a pointer to grpc_subchannel_call and the /** Call data. Holds a pointer to grpc_subchannel_call and the
associated machinery to create such a pointer. associated machinery to create such a pointer.
Handles queueing of stream ops until a call object is ready, waiting Handles queueing of stream ops until a call object is ready, waiting
@ -800,11 +777,10 @@ typedef struct client_channel_call_data {
grpc_call_context_element subchannel_call_context[GRPC_CONTEXT_COUNT]; grpc_call_context_element subchannel_call_context[GRPC_CONTEXT_COUNT];
grpc_polling_entity *pollent; grpc_polling_entity *pollent;
grpc_transport_stream_op_batch **waiting_ops; grpc_transport_stream_op_batch *waiting_for_pick_batches[MAX_WAITING_BATCHES];
size_t waiting_ops_count; size_t waiting_for_pick_batches_count;
size_t waiting_ops_capacity;
grpc_closure next_step; grpc_transport_stream_op_batch_payload *initial_metadata_payload;
grpc_call_stack *owning_call; grpc_call_stack *owning_call;
@ -853,57 +829,44 @@ grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
return get_call_or_error(call_elem->call_data).subchannel_call; return get_call_or_error(call_elem->call_data).subchannel_call;
} }
static void add_waiting_locked(call_data *calld, static void waiting_for_pick_batches_add_locked(
grpc_transport_stream_op_batch *op) { call_data *calld, grpc_transport_stream_op_batch *batch) {
GPR_TIMER_BEGIN("add_waiting_locked", 0); GPR_ASSERT(calld->waiting_for_pick_batches_count < MAX_WAITING_BATCHES);
if (calld->waiting_ops_count == calld->waiting_ops_capacity) { calld->waiting_for_pick_batches[calld->waiting_for_pick_batches_count++] =
calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity); batch;
calld->waiting_ops =
gpr_realloc(calld->waiting_ops,
calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
}
calld->waiting_ops[calld->waiting_ops_count++] = op;
GPR_TIMER_END("add_waiting_locked", 0);
} }
static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld, static void waiting_for_pick_batches_fail_locked(grpc_exec_ctx *exec_ctx,
grpc_error *error) { call_data *calld,
size_t i; grpc_error *error) {
for (i = 0; i < calld->waiting_ops_count; i++) { for (size_t i = 0; i < calld->waiting_for_pick_batches_count; ++i) {
grpc_transport_stream_op_batch_finish_with_failure( grpc_transport_stream_op_batch_finish_with_failure(
exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error)); exec_ctx, calld->waiting_for_pick_batches[i], GRPC_ERROR_REF(error));
} }
calld->waiting_ops_count = 0; calld->waiting_for_pick_batches_count = 0;
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) { static void waiting_for_pick_batches_resume_locked(grpc_exec_ctx *exec_ctx,
if (calld->waiting_ops_count == 0) { call_data *calld) {
return; if (calld->waiting_for_pick_batches_count == 0) return;
} call_or_error coe = get_call_or_error(calld);
if (coe.error != GRPC_ERROR_NONE) {
call_or_error call = get_call_or_error(calld); waiting_for_pick_batches_fail_locked(exec_ctx, calld,
grpc_transport_stream_op_batch **ops = calld->waiting_ops; GRPC_ERROR_REF(coe.error));
size_t nops = calld->waiting_ops_count;
if (call.error != GRPC_ERROR_NONE) {
fail_locked(exec_ctx, calld, GRPC_ERROR_REF(call.error));
return; return;
} }
calld->waiting_ops = NULL; for (size_t i = 0; i < calld->waiting_for_pick_batches_count; ++i) {
calld->waiting_ops_count = 0; grpc_subchannel_call_process_op(exec_ctx, coe.subchannel_call,
calld->waiting_ops_capacity = 0; calld->waiting_for_pick_batches[i]);
for (size_t i = 0; i < nops; i++) {
grpc_subchannel_call_process_op(exec_ctx, call.subchannel_call, ops[i]);
} }
gpr_free(ops); calld->waiting_for_pick_batches_count = 0;
} }
// Sets calld->method_params and calld->retry_throttle_data. // Applies service config to the call. Must be invoked once we know
// If the method params specify a timeout, populates // that the resolver has returned results to the channel.
// *per_method_deadline and returns true. static void apply_service_config_to_call_locked(grpc_exec_ctx *exec_ctx,
static bool set_call_method_params_from_service_config_locked( grpc_call_element *elem) {
grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
gpr_timespec *per_method_deadline) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
if (chand->retry_throttle_data != NULL) { if (chand->retry_throttle_data != NULL) {
@ -915,39 +878,48 @@ static bool set_call_method_params_from_service_config_locked(
exec_ctx, chand->method_params_table, calld->path); exec_ctx, chand->method_params_table, calld->path);
if (calld->method_params != NULL) { if (calld->method_params != NULL) {
method_parameters_ref(calld->method_params); method_parameters_ref(calld->method_params);
if (gpr_time_cmp(calld->method_params->timeout, // If the deadline from the service config is shorter than the one
// from the client API, reset the deadline timer.
if (chand->deadline_checking_enabled &&
gpr_time_cmp(calld->method_params->timeout,
gpr_time_0(GPR_TIMESPAN)) != 0) { gpr_time_0(GPR_TIMESPAN)) != 0) {
*per_method_deadline = const gpr_timespec per_method_deadline =
gpr_time_add(calld->call_start_time, calld->method_params->timeout); gpr_time_add(calld->call_start_time, calld->method_params->timeout);
return true; if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
calld->deadline = per_method_deadline;
grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
}
} }
} }
} }
return false;
} }
static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx, static void create_subchannel_call_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) { call_data *calld, grpc_error *error) {
/* apply service-config level configuration to the call (now that we're grpc_subchannel_call *subchannel_call = NULL;
* certain it exists) */ const grpc_connected_subchannel_call_args call_args = {
call_data *calld = elem->call_data; .pollent = calld->pollent,
channel_data *chand = elem->channel_data; .path = calld->path,
gpr_timespec per_method_deadline; .start_time = calld->call_start_time,
if (set_call_method_params_from_service_config_locked(exec_ctx, elem, .deadline = calld->deadline,
&per_method_deadline)) { .arena = calld->arena,
// If the deadline from the service config is shorter than the one .context = calld->subchannel_call_context};
// from the client API, reset the deadline timer. grpc_error *new_error = grpc_connected_subchannel_create_call(
if (chand->deadline_checking_enabled && exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
gpr_time_cmp(per_method_deadline, calld->deadline) < 0) { GPR_ASSERT(set_call_or_error(
calld->deadline = per_method_deadline; calld, (call_or_error){.subchannel_call = subchannel_call}));
grpc_deadline_state_reset(exec_ctx, elem, calld->deadline); if (new_error != GRPC_ERROR_NONE) {
} new_error = grpc_error_add_child(new_error, error);
waiting_for_pick_batches_fail_locked(exec_ctx, calld, new_error);
} else {
waiting_for_pick_batches_resume_locked(exec_ctx, calld);
} }
GRPC_ERROR_UNREF(error);
} }
static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg, static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_error *error) { grpc_error *error) {
grpc_call_element *elem = arg;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
GPR_ASSERT(calld->pick_pending); GPR_ASSERT(calld->pick_pending);
@ -956,6 +928,7 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
chand->interested_parties); chand->interested_parties);
call_or_error coe = get_call_or_error(calld); call_or_error coe = get_call_or_error(calld);
if (calld->connected_subchannel == NULL) { if (calld->connected_subchannel == NULL) {
// Failed to create subchannel.
grpc_error *failure = grpc_error *failure =
error == GRPC_ERROR_NONE error == GRPC_ERROR_NONE
? GRPC_ERROR_CREATE_FROM_STATIC_STRING( ? GRPC_ERROR_CREATE_FROM_STATIC_STRING(
@ -963,7 +936,7 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
: GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( : GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Failed to create subchannel", &error, 1); "Failed to create subchannel", &error, 1);
set_call_or_error(calld, (call_or_error){.error = GRPC_ERROR_REF(failure)}); set_call_or_error(calld, (call_or_error){.error = GRPC_ERROR_REF(failure)});
fail_locked(exec_ctx, calld, failure); waiting_for_pick_batches_fail_locked(exec_ctx, calld, failure);
} else if (coe.error != GRPC_ERROR_NONE) { } else if (coe.error != GRPC_ERROR_NONE) {
/* already cancelled before subchannel became ready */ /* already cancelled before subchannel became ready */
grpc_error *child_errors[] = {error, coe.error}; grpc_error *child_errors[] = {error, coe.error};
@ -977,29 +950,13 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS, grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_DEADLINE_EXCEEDED); GRPC_STATUS_DEADLINE_EXCEEDED);
} }
fail_locked(exec_ctx, calld, cancellation_error); waiting_for_pick_batches_fail_locked(exec_ctx, calld, cancellation_error);
} else { } else {
/* Create call on subchannel. */ /* Create call on subchannel. */
grpc_subchannel_call *subchannel_call = NULL; create_subchannel_call_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
const grpc_connected_subchannel_call_args call_args = {
.pollent = calld->pollent,
.path = calld->path,
.start_time = calld->call_start_time,
.deadline = calld->deadline,
.arena = calld->arena,
.context = calld->subchannel_call_context};
grpc_error *new_error = grpc_connected_subchannel_create_call(
exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
GPR_ASSERT(set_call_or_error(
calld, (call_or_error){.subchannel_call = subchannel_call}));
if (new_error != GRPC_ERROR_NONE) {
new_error = grpc_error_add_child(new_error, error);
fail_locked(exec_ctx, calld, new_error);
} else {
retry_waiting_locked(exec_ctx, calld);
}
} }
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
GRPC_ERROR_UNREF(error);
} }
static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
@ -1013,41 +970,32 @@ static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
} }
} }
/** Return true if subchannel is available immediately (in which case
subchannel_ready_locked() should not be called), or false otherwise (in
which case subchannel_ready_locked() should be called when the subchannel
is available). */
static bool pick_subchannel_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem);
typedef struct { typedef struct {
grpc_metadata_batch *initial_metadata;
uint32_t initial_metadata_flags;
grpc_connected_subchannel **connected_subchannel;
grpc_call_context_element *subchannel_call_context;
grpc_closure *on_ready;
grpc_call_element *elem; grpc_call_element *elem;
bool cancelled;
grpc_closure closure; grpc_closure closure;
} continue_picking_args; } pick_after_resolver_result_args;
/** Return true if subchannel is available immediately (in which case on_ready static void continue_picking_after_resolver_result_locked(
should not be called), or false otherwise (in which case on_ready should be grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
called when the subchannel is available). */ pick_after_resolver_result_args *args = arg;
static bool pick_subchannel_locked( if (args->cancelled) {
grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
grpc_connected_subchannel **connected_subchannel,
grpc_call_context_element *subchannel_call_context, grpc_closure *on_ready);
static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
continue_picking_args *cpa = arg;
if (cpa->connected_subchannel == NULL) {
/* cancelled, do nothing */ /* cancelled, do nothing */
} else if (error != GRPC_ERROR_NONE) { } else if (error != GRPC_ERROR_NONE) {
GRPC_CLOSURE_SCHED(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error)); subchannel_ready_locked(exec_ctx, args->elem, GRPC_ERROR_REF(error));
} else { } else {
if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata, if (pick_subchannel_locked(exec_ctx, args->elem)) {
cpa->initial_metadata_flags, subchannel_ready_locked(exec_ctx, args->elem, GRPC_ERROR_NONE);
cpa->connected_subchannel,
cpa->subchannel_call_context, cpa->on_ready)) {
GRPC_CLOSURE_SCHED(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
} }
} }
gpr_free(cpa); gpr_free(args);
} }
static void cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
@ -1059,39 +1007,85 @@ static void cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
&calld->connected_subchannel, &calld->connected_subchannel,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
} }
for (grpc_closure *closure = chand->waiting_for_config_closures.head; // If we don't yet have a resolver result, then a closure for
// continue_picking_after_resolver_result_locked() will have been added to
// chand->waiting_for_resolver_result_closures, and it may not be invoked
// until after this call has been destroyed. We mark the operation as
// cancelled, so that when continue_picking_after_resolver_result_locked()
// is called, it will be a no-op. We also immediately invoke
// subchannel_ready_locked() to propagate the error back to the caller.
for (grpc_closure *closure = chand->waiting_for_resolver_result_closures.head;
closure != NULL; closure = closure->next_data.next) { closure != NULL; closure = closure->next_data.next) {
continue_picking_args *cpa = closure->cb_arg; pick_after_resolver_result_args *args = closure->cb_arg;
if (cpa->connected_subchannel == &calld->connected_subchannel) { if (!args->cancelled && args->elem == elem) {
cpa->connected_subchannel = NULL; args->cancelled = true;
GRPC_CLOSURE_SCHED(exec_ctx, cpa->on_ready, subchannel_ready_locked(exec_ctx, elem,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Pick cancelled", &error, 1)); "Pick cancelled", &error, 1));
} }
} }
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
static bool pick_subchannel_locked( // State for pick callback that holds a reference to the LB policy
grpc_exec_ctx *exec_ctx, grpc_call_element *elem, // from which the pick was requested.
grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags, typedef struct {
grpc_connected_subchannel **connected_subchannel, grpc_lb_policy *lb_policy;
grpc_call_context_element *subchannel_call_context, grpc_call_element *elem;
grpc_closure *on_ready) { grpc_closure closure;
GPR_TIMER_BEGIN("pick_subchannel", 0); } pick_callback_args;
// Callback invoked by grpc_lb_policy_pick_locked() for async picks.
// Unrefs the LB policy after invoking subchannel_ready_locked().
static void pick_callback_done_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
pick_callback_args *args = arg;
GPR_ASSERT(args != NULL);
GPR_ASSERT(args->lb_policy != NULL);
subchannel_ready_locked(exec_ctx, args->elem, GRPC_ERROR_REF(error));
GRPC_LB_POLICY_UNREF(exec_ctx, args->lb_policy, "pick_subchannel");
gpr_free(args);
}
// Takes a ref to chand->lb_policy and calls grpc_lb_policy_pick_locked().
// If the pick was completed synchronously, unrefs the LB policy and
// returns true.
static bool pick_callback_start_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_lb_policy_pick_args *inputs) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
pick_callback_args *pick_args = gpr_zalloc(sizeof(*pick_args));
GRPC_LB_POLICY_REF(chand->lb_policy, "pick_subchannel");
pick_args->lb_policy = chand->lb_policy;
pick_args->elem = elem;
GRPC_CLOSURE_INIT(&pick_args->closure, pick_callback_done_locked, pick_args,
grpc_combiner_scheduler(chand->combiner));
const bool pick_done = grpc_lb_policy_pick_locked(
exec_ctx, chand->lb_policy, inputs, &calld->connected_subchannel,
calld->subchannel_call_context, NULL, &pick_args->closure);
if (pick_done) {
/* synchronous grpc_lb_policy_pick call. Unref the LB policy. */
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "pick_subchannel");
gpr_free(pick_args);
}
return pick_done;
}
GPR_ASSERT(connected_subchannel); static bool pick_subchannel_locked(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
GPR_TIMER_BEGIN("pick_subchannel", 0);
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
bool pick_done = false;
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
apply_final_configuration_locked(exec_ctx, elem); apply_service_config_to_call_locked(exec_ctx, elem);
grpc_lb_policy *lb_policy = chand->lb_policy;
GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
// If the application explicitly set wait_for_ready, use that. // If the application explicitly set wait_for_ready, use that.
// Otherwise, if the service config specified a value for this // Otherwise, if the service config specified a value for this
// method, use that. // method, use that.
uint32_t initial_metadata_flags =
calld->initial_metadata_payload->send_initial_metadata
.send_initial_metadata_flags;
const bool wait_for_ready_set_from_api = const bool wait_for_ready_set_from_api =
initial_metadata_flags & initial_metadata_flags &
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET; GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
@ -1107,78 +1101,57 @@ static bool pick_subchannel_locked(
} }
} }
const grpc_lb_policy_pick_args inputs = { const grpc_lb_policy_pick_args inputs = {
initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem}; calld->initial_metadata_payload->send_initial_metadata
.send_initial_metadata,
// Wrap the user-provided callback in order to hold a strong reference to initial_metadata_flags, &calld->lb_token_mdelem};
// the LB policy for the duration of the pick. pick_done = pick_callback_start_locked(exec_ctx, elem, &inputs);
wrapped_on_pick_closure_arg *w_on_pick_arg = } else if (chand->resolver != NULL) {
gpr_zalloc(sizeof(*w_on_pick_arg)); if (!chand->started_resolving) {
GRPC_CLOSURE_INIT(&w_on_pick_arg->wrapper_closure, chand->started_resolving = true;
wrapped_on_pick_closure_cb, w_on_pick_arg, GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
grpc_schedule_on_exec_ctx); grpc_resolver_next_locked(exec_ctx, chand->resolver,
w_on_pick_arg->wrapped_closure = on_ready; &chand->resolver_result,
GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel_wrapping"); &chand->on_resolver_result_changed);
w_on_pick_arg->lb_policy = lb_policy;
const bool pick_done = grpc_lb_policy_pick_locked(
exec_ctx, lb_policy, &inputs, connected_subchannel,
subchannel_call_context, NULL, &w_on_pick_arg->wrapper_closure);
if (pick_done) {
/* synchronous grpc_lb_policy_pick call. Unref the LB policy. */
GRPC_LB_POLICY_UNREF(exec_ctx, w_on_pick_arg->lb_policy,
"pick_subchannel_wrapping");
gpr_free(w_on_pick_arg);
} }
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel"); pick_after_resolver_result_args *args =
GPR_TIMER_END("pick_subchannel", 0); (pick_after_resolver_result_args *)gpr_zalloc(sizeof(*args));
return pick_done; args->elem = elem;
} GRPC_CLOSURE_INIT(&args->closure,
if (chand->resolver != NULL && !chand->started_resolving) { continue_picking_after_resolver_result_locked, args,
chand->started_resolving = true;
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
grpc_resolver_next_locked(exec_ctx, chand->resolver,
&chand->resolver_result,
&chand->on_resolver_result_changed);
}
if (chand->resolver != NULL) {
continue_picking_args *cpa = gpr_malloc(sizeof(*cpa));
cpa->initial_metadata = initial_metadata;
cpa->initial_metadata_flags = initial_metadata_flags;
cpa->connected_subchannel = connected_subchannel;
cpa->subchannel_call_context = subchannel_call_context;
cpa->on_ready = on_ready;
cpa->elem = elem;
GRPC_CLOSURE_INIT(&cpa->closure, continue_picking_locked, cpa,
grpc_combiner_scheduler(chand->combiner)); grpc_combiner_scheduler(chand->combiner));
grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure, grpc_closure_list_append(&chand->waiting_for_resolver_result_closures,
GRPC_ERROR_NONE); &args->closure, GRPC_ERROR_NONE);
} else { } else {
GRPC_CLOSURE_SCHED(exec_ctx, on_ready, subchannel_ready_locked(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected")); exec_ctx, elem, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
} }
GPR_TIMER_END("pick_subchannel", 0); GPR_TIMER_END("pick_subchannel", 0);
return false; return pick_done;
} }
static void start_transport_stream_op_batch_locked_inner( static void start_transport_stream_op_batch_locked(grpc_exec_ctx *exec_ctx,
grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op, void *arg,
grpc_call_element *elem) { grpc_error *error_ignored) {
channel_data *chand = elem->channel_data; GPR_TIMER_BEGIN("start_transport_stream_op_batch_locked", 0);
grpc_transport_stream_op_batch *op = arg;
grpc_call_element *elem = op->handler_private.extra_arg;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
/* need to recheck that another thread hasn't set the call */ /* need to recheck that another thread hasn't set the call */
call_or_error coe = get_call_or_error(calld); call_or_error coe = get_call_or_error(calld);
if (coe.error != GRPC_ERROR_NONE) { if (coe.error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure( grpc_transport_stream_op_batch_finish_with_failure(
exec_ctx, op, GRPC_ERROR_REF(coe.error)); exec_ctx, op, GRPC_ERROR_REF(coe.error));
/* early out */ goto done;
return;
} }
if (coe.subchannel_call != NULL) { if (coe.subchannel_call != NULL) {
grpc_subchannel_call_process_op(exec_ctx, coe.subchannel_call, op); grpc_subchannel_call_process_op(exec_ctx, coe.subchannel_call, op);
/* early out */ goto done;
return;
} }
// Add to waiting-for-pick list. If we succeed in getting a
// subchannel call below, we'll handle this batch (along with any
// other waiting batches) in waiting_for_pick_batches_resume_locked().
waiting_for_pick_batches_add_locked(calld, op);
/* if this is a cancellation, then we can raise our cancelled flag */ /* if this is a cancellation, then we can raise our cancelled flag */
if (op->cancel_stream) { if (op->cancel_stream) {
grpc_error *error = op->payload->cancel_stream.cancel_error; grpc_error *error = op->payload->cancel_stream.cancel_error;
@ -1190,30 +1163,22 @@ static void start_transport_stream_op_batch_locked_inner(
set_call_or_error(calld, (call_or_error){.error = GRPC_ERROR_REF(error)}); set_call_or_error(calld, (call_or_error){.error = GRPC_ERROR_REF(error)});
if (calld->pick_pending) { if (calld->pick_pending) {
cancel_pick_locked(exec_ctx, elem, GRPC_ERROR_REF(error)); cancel_pick_locked(exec_ctx, elem, GRPC_ERROR_REF(error));
} else {
fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
} }
grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, waiting_for_pick_batches_fail_locked(exec_ctx, calld,
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
/* early out */ goto done;
return;
} }
/* if we don't have a subchannel, try to get one */ /* if we don't have a subchannel, try to get one */
if (!calld->pick_pending && calld->connected_subchannel == NULL && if (!calld->pick_pending && calld->connected_subchannel == NULL &&
op->send_initial_metadata) { op->send_initial_metadata) {
calld->initial_metadata_payload = op->payload;
calld->pick_pending = true; calld->pick_pending = true;
GRPC_CLOSURE_INIT(&calld->next_step, subchannel_ready_locked, elem,
grpc_combiner_scheduler(chand->combiner));
GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel"); GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
/* If a subchannel is not available immediately, the polling entity from /* If a subchannel is not available immediately, the polling entity from
call_data should be provided to channel_data's interested_parties, so call_data should be provided to channel_data's interested_parties, so
that IO of the lb_policy and resolver could be done under it. */ that IO of the lb_policy and resolver could be done under it. */
if (pick_subchannel_locked( if (pick_subchannel_locked(exec_ctx, elem)) {
exec_ctx, elem, // Pick was returned synchronously.
op->payload->send_initial_metadata.send_initial_metadata,
op->payload->send_initial_metadata.send_initial_metadata_flags,
&calld->connected_subchannel, calld->subchannel_call_context,
&calld->next_step)) {
calld->pick_pending = false; calld->pick_pending = false;
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
if (calld->connected_subchannel == NULL) { if (calld->connected_subchannel == NULL) {
@ -1221,42 +1186,20 @@ static void start_transport_stream_op_batch_locked_inner(
"Call dropped by load balancing policy"); "Call dropped by load balancing policy");
set_call_or_error(calld, set_call_or_error(calld,
(call_or_error){.error = GRPC_ERROR_REF(error)}); (call_or_error){.error = GRPC_ERROR_REF(error)});
fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error)); waiting_for_pick_batches_fail_locked(exec_ctx, calld, error);
grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error); } else {
return; // Early out. // Create subchannel call.
create_subchannel_call_locked(exec_ctx, calld, GRPC_ERROR_NONE);
} }
} else { } else {
grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent, grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
chand->interested_parties); chand->interested_parties);
} }
} }
/* if we've got a subchannel, then let's ask it to create a call */ done:
if (!calld->pick_pending && calld->connected_subchannel != NULL) { GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
grpc_subchannel_call *subchannel_call = NULL; "start_transport_stream_op_batch");
const grpc_connected_subchannel_call_args call_args = { GPR_TIMER_END("start_transport_stream_op_batch_locked", 0);
.pollent = calld->pollent,
.path = calld->path,
.start_time = calld->call_start_time,
.deadline = calld->deadline,
.arena = calld->arena,
.context = calld->subchannel_call_context};
grpc_error *error = grpc_connected_subchannel_create_call(
exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
GPR_ASSERT(set_call_or_error(
calld, (call_or_error){.subchannel_call = subchannel_call}));
if (error != GRPC_ERROR_NONE) {
fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error);
} else {
retry_waiting_locked(exec_ctx, calld);
/* recurse to retry */
start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem);
}
/* early out */
return;
}
/* nothing to be done but wait */
add_waiting_locked(calld, op);
} }
static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
@ -1279,30 +1222,6 @@ static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
GRPC_ERROR_REF(error)); GRPC_ERROR_REF(error));
} }
static void start_transport_stream_op_batch_locked(grpc_exec_ctx *exec_ctx,
void *arg,
grpc_error *error_ignored) {
GPR_TIMER_BEGIN("start_transport_stream_op_batch_locked", 0);
grpc_transport_stream_op_batch *op = arg;
grpc_call_element *elem = op->handler_private.extra_arg;
call_data *calld = elem->call_data;
if (op->recv_trailing_metadata) {
GPR_ASSERT(op->on_complete != NULL);
calld->original_on_complete = op->on_complete;
GRPC_CLOSURE_INIT(&calld->on_complete, on_complete, elem,
grpc_schedule_on_exec_ctx);
op->on_complete = &calld->on_complete;
}
start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem);
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
"start_transport_stream_op_batch");
GPR_TIMER_END("start_transport_stream_op_batch_locked", 0);
}
/* The logic here is fairly complicated, due to (a) the fact that we /* The logic here is fairly complicated, due to (a) the fact that we
need to handle the case where we receive the send op before the need to handle the case where we receive the send op before the
initial metadata op, and (b) the need for efficiency, especially in initial metadata op, and (b) the need for efficiency, especially in
@ -1321,6 +1240,15 @@ static void cc_start_transport_stream_op_batch(
grpc_deadline_state_client_start_transport_stream_op_batch(exec_ctx, elem, grpc_deadline_state_client_start_transport_stream_op_batch(exec_ctx, elem,
op); op);
} }
// Intercept on_complete for recv_trailing_metadata so that we can
// check retry throttle status.
if (op->recv_trailing_metadata) {
GPR_ASSERT(op->on_complete != NULL);
calld->original_on_complete = op->on_complete;
GRPC_CLOSURE_INIT(&calld->on_complete, on_complete, elem,
grpc_schedule_on_exec_ctx);
op->on_complete = &calld->on_complete;
}
/* try to (atomically) get the call */ /* try to (atomically) get the call */
call_or_error coe = get_call_or_error(calld); call_or_error coe = get_call_or_error(calld);
GPR_TIMER_BEGIN("cc_start_transport_stream_op_batch", 0); GPR_TIMER_BEGIN("cc_start_transport_stream_op_batch", 0);
@ -1390,7 +1318,7 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
"client_channel_destroy_call"); "client_channel_destroy_call");
} }
GPR_ASSERT(!calld->pick_pending); GPR_ASSERT(!calld->pick_pending);
GPR_ASSERT(calld->waiting_ops_count == 0); GPR_ASSERT(calld->waiting_for_pick_batches_count == 0);
if (calld->connected_subchannel != NULL) { if (calld->connected_subchannel != NULL) {
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel, GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
"picked"); "picked");
@ -1401,7 +1329,6 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
calld->subchannel_call_context[i].value); calld->subchannel_call_context[i].value);
} }
} }
gpr_free(calld->waiting_ops);
GRPC_CLOSURE_SCHED(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
} }

@ -78,6 +78,9 @@ void grpc_client_channel_init(void) {
GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter, GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter,
(void *)&grpc_client_channel_filter); (void *)&grpc_client_channel_filter);
grpc_http_connect_register_handshaker_factory(); grpc_http_connect_register_handshaker_factory();
#ifndef NDEBUG
grpc_register_tracer("resolver_refcount", &grpc_trace_resolver_refcount);
#endif
} }
void grpc_client_channel_shutdown(void) { void grpc_client_channel_shutdown(void) {

@ -21,6 +21,10 @@
#define WEAK_REF_BITS 16 #define WEAK_REF_BITS 16
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_lb_policy_refcount = GRPC_TRACER_INITIALIZER(false);
#endif
void grpc_lb_policy_init(grpc_lb_policy *policy, void grpc_lb_policy_init(grpc_lb_policy *policy,
const grpc_lb_policy_vtable *vtable, const grpc_lb_policy_vtable *vtable,
grpc_combiner *combiner) { grpc_combiner *combiner) {
@ -30,7 +34,7 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
policy->combiner = GRPC_COMBINER_REF(combiner, "lb_policy"); policy->combiner = GRPC_COMBINER_REF(combiner, "lb_policy");
} }
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG #ifndef NDEBUG
#define REF_FUNC_EXTRA_ARGS , const char *file, int line, const char *reason #define REF_FUNC_EXTRA_ARGS , const char *file, int line, const char *reason
#define REF_MUTATE_EXTRA_ARGS REF_FUNC_EXTRA_ARGS, const char *purpose #define REF_MUTATE_EXTRA_ARGS REF_FUNC_EXTRA_ARGS, const char *purpose
#define REF_FUNC_PASS_ARGS(new_reason) , file, line, new_reason #define REF_FUNC_PASS_ARGS(new_reason) , file, line, new_reason
@ -46,11 +50,12 @@ static gpr_atm ref_mutate(grpc_lb_policy *c, gpr_atm delta,
int barrier REF_MUTATE_EXTRA_ARGS) { int barrier REF_MUTATE_EXTRA_ARGS) {
gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta) gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
: gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG #ifndef NDEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, if (GRPC_TRACER_ON(grpc_trace_lb_policy_refcount)) {
"LB_POLICY: 0x%" PRIxPTR " %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
" [%s]", "LB_POLICY: 0x%p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c,
(intptr_t)c, purpose, old_val, old_val + delta, reason); purpose, old_val, old_val + delta, reason);
}
#endif #endif
return old_val; return old_val;
} }

@ -29,6 +29,10 @@ typedef struct grpc_lb_policy grpc_lb_policy;
typedef struct grpc_lb_policy_vtable grpc_lb_policy_vtable; typedef struct grpc_lb_policy_vtable grpc_lb_policy_vtable;
typedef struct grpc_lb_policy_args grpc_lb_policy_args; typedef struct grpc_lb_policy_args grpc_lb_policy_args;
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_lb_policy_refcount;
#endif
struct grpc_lb_policy { struct grpc_lb_policy {
const grpc_lb_policy_vtable *vtable; const grpc_lb_policy_vtable *vtable;
gpr_atm ref_pair; gpr_atm ref_pair;
@ -96,8 +100,7 @@ struct grpc_lb_policy_vtable {
const grpc_lb_policy_args *args); const grpc_lb_policy_args *args);
}; };
//#define GRPC_LB_POLICY_REFCOUNT_DEBUG #ifndef NDEBUG
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
/* Strong references: the policy will shutdown when they reach zero */ /* Strong references: the policy will shutdown when they reach zero */
#define GRPC_LB_POLICY_REF(p, r) \ #define GRPC_LB_POLICY_REF(p, r) \

@ -1880,6 +1880,9 @@ static bool maybe_add_client_load_reporting_filter(
void grpc_lb_policy_grpclb_init() { void grpc_lb_policy_grpclb_init() {
grpc_register_lb_policy(grpc_glb_lb_factory_create()); grpc_register_lb_policy(grpc_glb_lb_factory_create());
grpc_register_tracer("glb", &grpc_lb_glb_trace); grpc_register_tracer("glb", &grpc_lb_glb_trace);
#ifndef NDEBUG
grpc_register_tracer("lb_policy_refcount", &grpc_trace_lb_policy_refcount);
#endif
grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_client_load_reporting_filter, maybe_add_client_load_reporting_filter,

@ -95,6 +95,9 @@ static void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
gpr_free(p->subchannels); gpr_free(p->subchannels);
gpr_free(p->new_subchannels); gpr_free(p->new_subchannels);
gpr_free(p); gpr_free(p);
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p destroyed.", (void *)p);
}
} }
static void pf_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { static void pf_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
@ -268,11 +271,20 @@ static void stop_connectivity_watchers(grpc_exec_ctx *exec_ctx,
pick_first_lb_policy *p) { pick_first_lb_policy *p) {
if (p->num_subchannels > 0) { if (p->num_subchannels > 0) {
GPR_ASSERT(p->selected == NULL); GPR_ASSERT(p->selected == NULL);
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p unsubscribing from subchannel %p",
(void *)p, (void *)p->subchannels[p->checking_subchannel]);
}
grpc_subchannel_notify_on_state_change( grpc_subchannel_notify_on_state_change(
exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL, exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
&p->connectivity_changed); &p->connectivity_changed);
p->updating_subchannels = true; p->updating_subchannels = true;
} else if (p->selected != NULL) { } else if (p->selected != NULL) {
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG,
"Pick First %p unsubscribing from selected subchannel %p",
(void *)p, (void *)p->selected);
}
grpc_connected_subchannel_notify_on_state_change( grpc_connected_subchannel_notify_on_state_change(
exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed); exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed);
p->updating_selected = true; p->updating_selected = true;
@ -451,12 +463,25 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_subchannel *selected_subchannel; grpc_subchannel *selected_subchannel;
pending_pick *pp; pending_pick *pp;
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(
GPR_DEBUG,
"Pick First %p connectivity changed. Updating selected: %d; Updating "
"subchannels: %d; Checking %lu index (%lu total); State: %d; ",
(void *)p, p->updating_selected, p->updating_subchannels,
(unsigned long)p->checking_subchannel,
(unsigned long)p->num_subchannels, p->checking_connectivity);
}
bool restart = false; bool restart = false;
if (p->updating_selected && error == GRPC_ERROR_CANCELLED) { if (p->updating_selected && error != GRPC_ERROR_NONE) {
/* Captured the unsubscription for p->selected */ /* Captured the unsubscription for p->selected */
GPR_ASSERT(p->selected != NULL); GPR_ASSERT(p->selected != NULL);
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->selected, GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->selected,
"pf_update_connectivity"); "pf_update_connectivity");
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p unreffing selected subchannel %p",
(void *)p, (void *)p->selected);
}
p->updating_selected = false; p->updating_selected = false;
if (p->num_new_subchannels == 0) { if (p->num_new_subchannels == 0) {
p->selected = NULL; p->selected = NULL;
@ -464,12 +489,16 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
} }
restart = true; restart = true;
} }
if (p->updating_subchannels && error == GRPC_ERROR_CANCELLED) { if (p->updating_subchannels && error != GRPC_ERROR_NONE) {
/* Captured the unsubscription for the checking subchannel */ /* Captured the unsubscription for the checking subchannel */
GPR_ASSERT(p->selected == NULL); GPR_ASSERT(p->selected == NULL);
for (size_t i = 0; i < p->num_subchannels; i++) { for (size_t i = 0; i < p->num_subchannels; i++) {
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i],
"pf_update_connectivity"); "pf_update_connectivity");
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p unreffing subchannel %p", (void *)p,
(void *)p->subchannels[i]);
}
} }
gpr_free(p->subchannels); gpr_free(p->subchannels);
p->subchannels = NULL; p->subchannels = NULL;
@ -481,14 +510,12 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
if (restart) { if (restart) {
p->selected = NULL; p->selected = NULL;
p->selected_key = NULL; p->selected_key = NULL;
GPR_ASSERT(p->new_subchannels != NULL); GPR_ASSERT(p->new_subchannels != NULL);
GPR_ASSERT(p->num_new_subchannels > 0); GPR_ASSERT(p->num_new_subchannels > 0);
p->num_subchannels = p->num_new_subchannels; p->num_subchannels = p->num_new_subchannels;
p->subchannels = p->new_subchannels; p->subchannels = p->new_subchannels;
p->num_new_subchannels = 0; p->num_new_subchannels = 0;
p->new_subchannels = NULL; p->new_subchannels = NULL;
if (p->started_picking) { if (p->started_picking) {
/* If we were picking, continue to do so over the new subchannels, /* If we were picking, continue to do so over the new subchannels,
* starting from the 0th index. */ * starting from the 0th index. */
@ -542,7 +569,9 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
"picked_first"); "picked_first");
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) { if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_INFO, "Selected subchannel %p", (void *)p->selected); gpr_log(GPR_INFO,
"Pick First %p selected subchannel %p (connected %p)",
(void *)p, (void *)selected_subchannel, (void *)p->selected);
} }
p->selected_key = grpc_subchannel_get_key(selected_subchannel); p->selected_key = grpc_subchannel_get_key(selected_subchannel);
/* drop the pick list: we are connected now */ /* drop the pick list: we are connected now */
@ -568,7 +597,8 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
p->checking_subchannel = p->checking_subchannel =
(p->checking_subchannel + 1) % p->num_subchannels; (p->checking_subchannel + 1) % p->num_subchannels;
if (p->checking_subchannel == 0) { if (p->checking_subchannel == 0) {
/* only trigger transient failure when we've tried all alternatives */ /* only trigger transient failure when we've tried all alternatives
*/
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "connecting_transient_failure"); GRPC_ERROR_REF(error), "connecting_transient_failure");
@ -652,6 +682,9 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_args *args) { grpc_lb_policy_args *args) {
GPR_ASSERT(args->client_channel_factory != NULL); GPR_ASSERT(args->client_channel_factory != NULL);
pick_first_lb_policy *p = gpr_zalloc(sizeof(*p)); pick_first_lb_policy *p = gpr_zalloc(sizeof(*p));
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p created.", (void *)p);
}
pf_update_locked(exec_ctx, &p->base, args); pf_update_locked(exec_ctx, &p->base, args);
grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner); grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner);
GRPC_CLOSURE_INIT(&p->connectivity_changed, pf_connectivity_changed_locked, p, GRPC_CLOSURE_INIT(&p->connectivity_changed, pf_connectivity_changed_locked, p,

@ -126,6 +126,8 @@ struct rr_subchannel_list {
size_t num_ready; size_t num_ready;
/** how many subchannels are in state TRANSIENT_FAILURE */ /** how many subchannels are in state TRANSIENT_FAILURE */
size_t num_transient_failures; size_t num_transient_failures;
/** how many subchannels are in state SHUTDOWN */
size_t num_shutdown;
/** how many subchannels are in state IDLE */ /** how many subchannels are in state IDLE */
size_t num_idle; size_t num_idle;
@ -425,6 +427,9 @@ static void update_state_counters_locked(subchannel_data *sd) {
} else if (sd->prev_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { } else if (sd->prev_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
GPR_ASSERT(subchannel_list->num_transient_failures > 0); GPR_ASSERT(subchannel_list->num_transient_failures > 0);
--subchannel_list->num_transient_failures; --subchannel_list->num_transient_failures;
} else if (sd->prev_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
GPR_ASSERT(subchannel_list->num_shutdown > 0);
--subchannel_list->num_shutdown;
} else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) { } else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) {
GPR_ASSERT(subchannel_list->num_idle > 0); GPR_ASSERT(subchannel_list->num_idle > 0);
--subchannel_list->num_idle; --subchannel_list->num_idle;
@ -433,6 +438,8 @@ static void update_state_counters_locked(subchannel_data *sd) {
++subchannel_list->num_ready; ++subchannel_list->num_ready;
} else if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { } else if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
++subchannel_list->num_transient_failures; ++subchannel_list->num_transient_failures;
} else if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
++subchannel_list->num_shutdown;
} else if (sd->curr_connectivity_state == GRPC_CHANNEL_IDLE) { } else if (sd->curr_connectivity_state == GRPC_CHANNEL_IDLE) {
++subchannel_list->num_idle; ++subchannel_list->num_idle;
} }
@ -455,7 +462,8 @@ static grpc_connectivity_state update_lb_connectivity_status_locked(
* CHECK: sd->curr_connectivity_state == CONNECTING. * CHECK: sd->curr_connectivity_state == CONNECTING.
* *
* 3) RULE: ALL subchannels are SHUTDOWN => policy is SHUTDOWN. * 3) RULE: ALL subchannels are SHUTDOWN => policy is SHUTDOWN.
* CHECK: p->subchannel_list->num_subchannels = 0. * CHECK: p->subchannel_list->num_shutdown ==
* p->subchannel_list->num_subchannels.
* *
* 4) RULE: ALL subchannels are TRANSIENT_FAILURE => policy is * 4) RULE: ALL subchannels are TRANSIENT_FAILURE => policy is
* TRANSIENT_FAILURE. * TRANSIENT_FAILURE.
@ -464,37 +472,39 @@ static grpc_connectivity_state update_lb_connectivity_status_locked(
* 5) RULE: ALL subchannels are IDLE => policy is IDLE. * 5) RULE: ALL subchannels are IDLE => policy is IDLE.
* CHECK: p->num_idle == p->subchannel_list->num_subchannels. * CHECK: p->num_idle == p->subchannel_list->num_subchannels.
*/ */
grpc_connectivity_state new_state = sd->curr_connectivity_state;
rr_subchannel_list *subchannel_list = sd->subchannel_list; rr_subchannel_list *subchannel_list = sd->subchannel_list;
round_robin_lb_policy *p = subchannel_list->policy; round_robin_lb_policy *p = subchannel_list->policy;
if (subchannel_list->num_ready > 0) { /* 1) READY */ if (subchannel_list->num_ready > 0) { /* 1) READY */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_READY, grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_READY,
GRPC_ERROR_NONE, "rr_ready"); GRPC_ERROR_NONE, "rr_ready");
return GRPC_CHANNEL_READY; new_state = GRPC_CHANNEL_READY;
} else if (sd->curr_connectivity_state == } else if (sd->curr_connectivity_state ==
GRPC_CHANNEL_CONNECTING) { /* 2) CONNECTING */ GRPC_CHANNEL_CONNECTING) { /* 2) CONNECTING */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,
"rr_connecting"); "rr_connecting");
return GRPC_CHANNEL_CONNECTING; new_state = GRPC_CHANNEL_CONNECTING;
} else if (p->subchannel_list->num_subchannels == 0) { /* 3) SHUTDOWN */ } else if (p->subchannel_list->num_shutdown ==
p->subchannel_list->num_subchannels) { /* 3) SHUTDOWN */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error),
"rr_shutdown"); "rr_shutdown");
return GRPC_CHANNEL_SHUTDOWN; new_state = GRPC_CHANNEL_SHUTDOWN;
} else if (subchannel_list->num_transient_failures == } else if (subchannel_list->num_transient_failures ==
p->subchannel_list->num_subchannels) { /* 4) TRANSIENT_FAILURE */ p->subchannel_list->num_subchannels) { /* 4) TRANSIENT_FAILURE */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "rr_transient_failure"); GRPC_ERROR_REF(error), "rr_transient_failure");
return GRPC_CHANNEL_TRANSIENT_FAILURE; new_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
} else if (subchannel_list->num_idle == } else if (subchannel_list->num_idle ==
p->subchannel_list->num_subchannels) { /* 5) IDLE */ p->subchannel_list->num_subchannels) { /* 5) IDLE */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_IDLE, grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_IDLE,
GRPC_ERROR_NONE, "rr_idle"); GRPC_ERROR_NONE, "rr_idle");
return GRPC_CHANNEL_IDLE; new_state = GRPC_CHANNEL_IDLE;
} }
/* no change */ GRPC_ERROR_UNREF(error);
return sd->curr_connectivity_state; return new_state;
} }
static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
@ -571,13 +581,15 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
GPR_ASSERT(sd->subchannel_list == p->latest_pending_subchannel_list); GPR_ASSERT(sd->subchannel_list == p->latest_pending_subchannel_list);
GPR_ASSERT(!sd->subchannel_list->shutting_down); GPR_ASSERT(!sd->subchannel_list->shutting_down);
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
const unsigned long num_subchannels =
p->subchannel_list != NULL
? (unsigned long)p->subchannel_list->num_subchannels
: 0;
gpr_log(GPR_DEBUG, gpr_log(GPR_DEBUG,
"[RR %p] phasing out subchannel list %p (size %lu) in favor " "[RR %p] phasing out subchannel list %p (size %lu) in favor "
"of %p (size %lu)", "of %p (size %lu)",
(void *)p, (void *)p->subchannel_list, (void *)p, (void *)p->subchannel_list, num_subchannels,
(unsigned long)p->subchannel_list->num_subchannels, (void *)sd->subchannel_list, num_subchannels);
(void *)sd->subchannel_list,
(unsigned long)sd->subchannel_list->num_subchannels);
} }
if (p->subchannel_list != NULL) { if (p->subchannel_list != NULL) {
// dispose of the current subchannel_list // dispose of the current subchannel_list

@ -19,6 +19,10 @@
#include "src/core/ext/filters/client_channel/resolver.h" #include "src/core/ext/filters/client_channel/resolver.h"
#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/combiner.h"
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_resolver_refcount = GRPC_TRACER_INITIALIZER(false);
#endif
void grpc_resolver_init(grpc_resolver *resolver, void grpc_resolver_init(grpc_resolver *resolver,
const grpc_resolver_vtable *vtable, const grpc_resolver_vtable *vtable,
grpc_combiner *combiner) { grpc_combiner *combiner) {
@ -27,25 +31,30 @@ void grpc_resolver_init(grpc_resolver *resolver,
gpr_ref_init(&resolver->refs, 1); gpr_ref_init(&resolver->refs, 1);
} }
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_resolver_ref(grpc_resolver *resolver, grpc_closure_list *closure_list, void grpc_resolver_ref(grpc_resolver *resolver, const char *file, int line,
const char *file, int line, const char *reason) { const char *reason) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p ref %d -> %d %s", if (GRPC_TRACER_ON(grpc_trace_resolver_refcount)) {
resolver, (int)resolver->refs.count, (int)resolver->refs.count + 1, gpr_atm old_refs = gpr_atm_no_barrier_load(&resolver->refs.count);
reason); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"RESOLVER:%p ref %" PRIdPTR " -> %" PRIdPTR " %s", resolver,
old_refs, old_refs + 1, reason);
}
#else #else
void grpc_resolver_ref(grpc_resolver *resolver) { void grpc_resolver_ref(grpc_resolver *resolver) {
#endif #endif
gpr_ref(&resolver->refs); gpr_ref(&resolver->refs);
} }
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_resolver_unref(grpc_resolver *resolver, void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_closure_list *closure_list, const char *file, const char *file, int line, const char *reason) {
int line, const char *reason) { if (GRPC_TRACER_ON(grpc_trace_resolver_refcount)) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p unref %d -> %d %s", gpr_atm old_refs = gpr_atm_no_barrier_load(&resolver->refs.count);
resolver, (int)resolver->refs.count, (int)resolver->refs.count - 1, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
reason); "RESOLVER:%p unref %" PRIdPTR " -> %" PRIdPTR " %s", resolver,
old_refs, old_refs - 1, reason);
}
#else #else
void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
#endif #endif

@ -25,6 +25,10 @@
typedef struct grpc_resolver grpc_resolver; typedef struct grpc_resolver grpc_resolver;
typedef struct grpc_resolver_vtable grpc_resolver_vtable; typedef struct grpc_resolver_vtable grpc_resolver_vtable;
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_resolver_refcount;
#endif
/** \a grpc_resolver provides \a grpc_channel_args objects to its caller */ /** \a grpc_resolver provides \a grpc_channel_args objects to its caller */
struct grpc_resolver { struct grpc_resolver {
const grpc_resolver_vtable *vtable; const grpc_resolver_vtable *vtable;
@ -41,17 +45,17 @@ struct grpc_resolver_vtable {
grpc_channel_args **result, grpc_closure *on_complete); grpc_channel_args **result, grpc_closure *on_complete);
}; };
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG #ifndef NDEBUG
#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p), __FILE__, __LINE__, (r)) #define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p), __FILE__, __LINE__, (r))
#define GRPC_RESOLVER_UNREF(cl, p, r) \ #define GRPC_RESOLVER_UNREF(e, p, r) \
grpc_resolver_unref((cl), (p), __FILE__, __LINE__, (r)) grpc_resolver_unref((e), (p), __FILE__, __LINE__, (r))
void grpc_resolver_ref(grpc_resolver *policy, const char *file, int line, void grpc_resolver_ref(grpc_resolver *policy, const char *file, int line,
const char *reason); const char *reason);
void grpc_resolver_unref(grpc_resolver *policy, grpc_closure_list *closure_list, void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy,
const char *file, int line, const char *reason); const char *file, int line, const char *reason);
#else #else
#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p)) #define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p))
#define GRPC_RESOLVER_UNREF(cl, p, r) grpc_resolver_unref((cl), (p)) #define GRPC_RESOLVER_UNREF(e, p, r) grpc_resolver_unref((e), (p))
void grpc_resolver_ref(grpc_resolver *policy); void grpc_resolver_ref(grpc_resolver *policy);
void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy); void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy);
#endif #endif

@ -19,8 +19,6 @@
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H
#include <ares.h>
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/pollset_set.h"

@ -19,6 +19,8 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) #if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET)
#include <ares.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>

@ -56,6 +56,10 @@ typedef struct {
// grpc_resolver_next_locked()'s closure. // grpc_resolver_next_locked()'s closure.
grpc_channel_args* next_results; grpc_channel_args* next_results;
// Results to use for the pretended re-resolution in
// fake_resolver_channel_saw_error_locked().
grpc_channel_args* results_upon_error;
// pending next completion, or NULL // pending next completion, or NULL
grpc_closure* next_completion; grpc_closure* next_completion;
// target result address for next completion // target result address for next completion
@ -65,6 +69,7 @@ typedef struct {
static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) {
fake_resolver* r = (fake_resolver*)gr; fake_resolver* r = (fake_resolver*)gr;
grpc_channel_args_destroy(exec_ctx, r->next_results); grpc_channel_args_destroy(exec_ctx, r->next_results);
grpc_channel_args_destroy(exec_ctx, r->results_upon_error);
grpc_channel_args_destroy(exec_ctx, r->channel_args); grpc_channel_args_destroy(exec_ctx, r->channel_args);
gpr_free(r); gpr_free(r);
} }
@ -74,7 +79,9 @@ static void fake_resolver_shutdown_locked(grpc_exec_ctx* exec_ctx,
fake_resolver* r = (fake_resolver*)resolver; fake_resolver* r = (fake_resolver*)resolver;
if (r->next_completion != NULL) { if (r->next_completion != NULL) {
*r->target_result = NULL; *r->target_result = NULL;
GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(
exec_ctx, r->next_completion,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown"));
r->next_completion = NULL; r->next_completion = NULL;
} }
} }
@ -85,15 +92,19 @@ static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx,
*r->target_result = *r->target_result =
grpc_channel_args_union(r->next_results, r->channel_args); grpc_channel_args_union(r->next_results, r->channel_args);
grpc_channel_args_destroy(exec_ctx, r->next_results); grpc_channel_args_destroy(exec_ctx, r->next_results);
r->next_results = NULL;
GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
r->next_completion = NULL; r->next_completion = NULL;
r->next_results = NULL;
} }
} }
static void fake_resolver_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, static void fake_resolver_channel_saw_error_locked(grpc_exec_ctx* exec_ctx,
grpc_resolver* resolver) { grpc_resolver* resolver) {
fake_resolver* r = (fake_resolver*)resolver; fake_resolver* r = (fake_resolver*)resolver;
if (r->next_results == NULL && r->results_upon_error != NULL) {
// Pretend we re-resolved.
r->next_results = grpc_channel_args_copy(r->results_upon_error);
}
fake_resolver_maybe_finish_next_locked(exec_ctx, r); fake_resolver_maybe_finish_next_locked(exec_ctx, r);
} }
@ -149,6 +160,10 @@ static void set_response_cb(grpc_exec_ctx* exec_ctx, void* arg,
grpc_channel_args_destroy(exec_ctx, r->next_results); grpc_channel_args_destroy(exec_ctx, r->next_results);
} }
r->next_results = generator->next_response; r->next_results = generator->next_response;
if (r->results_upon_error != NULL) {
grpc_channel_args_destroy(exec_ctx, r->results_upon_error);
}
r->results_upon_error = grpc_channel_args_copy(generator->next_response);
fake_resolver_maybe_finish_next_locked(exec_ctx, r); fake_resolver_maybe_finish_next_locked(exec_ctx, r);
} }

@ -73,7 +73,9 @@ static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx,
sockaddr_resolver *r = (sockaddr_resolver *)resolver; sockaddr_resolver *r = (sockaddr_resolver *)resolver;
if (r->next_completion != NULL) { if (r->next_completion != NULL) {
*r->target_result = NULL; *r->target_result = NULL;
GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(
exec_ctx, r->next_completion,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown"));
r->next_completion = NULL; r->next_completion = NULL;
} }
} }

@ -140,25 +140,13 @@ struct grpc_subchannel_call {
static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel, static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
grpc_error *error); grpc_error *error);
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
#define REF_REASON reason #define REF_REASON reason
#define REF_LOG(name, p) \
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p ref %d -> %d %s", \
(name), (p), (p)->refs.count, (p)->refs.count + 1, reason)
#define UNREF_LOG(name, p) \
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p unref %d -> %d %s", \
(name), (p), (p)->refs.count, (p)->refs.count - 1, reason)
#define REF_MUTATE_EXTRA_ARGS \ #define REF_MUTATE_EXTRA_ARGS \
GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char *purpose GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char *purpose
#define REF_MUTATE_PURPOSE(x) , file, line, reason, x #define REF_MUTATE_PURPOSE(x) , file, line, reason, x
#else #else
#define REF_REASON "" #define REF_REASON ""
#define REF_LOG(name, p) \
do { \
} while (0)
#define UNREF_LOG(name, p) \
do { \
} while (0)
#define REF_MUTATE_EXTRA_ARGS #define REF_MUTATE_EXTRA_ARGS
#define REF_MUTATE_PURPOSE(x) #define REF_MUTATE_PURPOSE(x)
#endif #endif
@ -207,10 +195,12 @@ static gpr_atm ref_mutate(grpc_subchannel *c, gpr_atm delta,
int barrier REF_MUTATE_EXTRA_ARGS) { int barrier REF_MUTATE_EXTRA_ARGS) {
gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta) gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
: gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, if (GRPC_TRACER_ON(grpc_trace_stream_refcount)) {
"SUBCHANNEL: %p %s 0x%08" PRIxPTR " -> 0x%08" PRIxPTR " [%s]", c, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
purpose, old_val, old_val + delta, reason); "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c,
purpose, old_val, old_val + delta, reason);
}
#endif #endif
return old_val; return old_val;
} }

@ -37,7 +37,7 @@ typedef struct grpc_subchannel_call grpc_subchannel_call;
typedef struct grpc_subchannel_args grpc_subchannel_args; typedef struct grpc_subchannel_args grpc_subchannel_args;
typedef struct grpc_subchannel_key grpc_subchannel_key; typedef struct grpc_subchannel_key grpc_subchannel_key;
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
#define GRPC_SUBCHANNEL_REF(p, r) \ #define GRPC_SUBCHANNEL_REF(p, r) \
grpc_subchannel_ref((p), __FILE__, __LINE__, (r)) grpc_subchannel_ref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \

@ -255,6 +255,23 @@ static void continue_send_message(grpc_exec_ctx *exec_ctx,
} }
} }
static void handle_send_message_batch(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op_batch *op,
bool has_compression_algorithm) {
call_data *calld = elem->call_data;
if (!skip_compression(elem, op->payload->send_message.send_message->flags,
has_compression_algorithm)) {
calld->send_op = op;
calld->send_length = op->payload->send_message.send_message->length;
calld->send_flags = op->payload->send_message.send_message->flags;
continue_send_message(exec_ctx, elem);
} else {
/* pass control down the stack */
grpc_call_next_op(exec_ctx, elem, op);
}
}
static void compress_start_transport_stream_op_batch( static void compress_start_transport_stream_op_batch(
grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_transport_stream_op_batch *op) { grpc_transport_stream_op_batch *op) {
@ -307,8 +324,9 @@ static void compress_start_transport_stream_op_batch(
goto retry_send_im; goto retry_send_im;
} }
if (cur != INITIAL_METADATA_UNSEEN) { if (cur != INITIAL_METADATA_UNSEEN) {
grpc_call_next_op(exec_ctx, elem, handle_send_message_batch(exec_ctx, elem,
(grpc_transport_stream_op_batch *)cur); (grpc_transport_stream_op_batch *)cur,
has_compression_algorithm);
} }
} }
} }
@ -325,17 +343,8 @@ static void compress_start_transport_stream_op_batch(
break; break;
case HAS_COMPRESSION_ALGORITHM: case HAS_COMPRESSION_ALGORITHM:
case NO_COMPRESSION_ALGORITHM: case NO_COMPRESSION_ALGORITHM:
if (!skip_compression(elem, handle_send_message_batch(exec_ctx, elem, op,
op->payload->send_message.send_message->flags, cur == HAS_COMPRESSION_ALGORITHM);
cur == HAS_COMPRESSION_ALGORITHM)) {
calld->send_op = op;
calld->send_length = op->payload->send_message.send_message->length;
calld->send_flags = op->payload->send_message.send_message->flags;
continue_send_message(exec_ctx, elem);
} else {
/* pass control down the stack */
grpc_call_next_op(exec_ctx, elem, op);
}
break; break;
default: default:
if (cur & CANCELLED_BIT) { if (cur & CANCELLED_BIT) {

@ -23,6 +23,9 @@
void grpc_chttp2_plugin_init(void) { void grpc_chttp2_plugin_init(void) {
grpc_register_tracer("http", &grpc_http_trace); grpc_register_tracer("http", &grpc_http_trace);
grpc_register_tracer("flowctl", &grpc_flowctl_trace); grpc_register_tracer("flowctl", &grpc_flowctl_trace);
#ifndef NDEBUG
grpc_register_tracer("chttp2_refcount", &grpc_trace_chttp2_refcount);
#endif
} }
void grpc_chttp2_plugin_shutdown(void) {} void grpc_chttp2_plugin_shutdown(void) {}

@ -52,7 +52,7 @@
#define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024) #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
#define MAX_WINDOW 0x7fffffffu #define MAX_WINDOW 0x7fffffffu
#define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024) #define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
#define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024) #define DEFAULT_MAX_HEADER_LIST_SIZE (8 * 1024)
#define DEFAULT_CLIENT_KEEPALIVE_TIME_MS INT_MAX #define DEFAULT_CLIENT_KEEPALIVE_TIME_MS INT_MAX
#define DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_MS 20000 /* 20 seconds */ #define DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_MS 20000 /* 20 seconds */
@ -76,6 +76,10 @@ static bool g_default_keepalive_permit_without_calls =
grpc_tracer_flag grpc_http_trace = GRPC_TRACER_INITIALIZER(false); grpc_tracer_flag grpc_http_trace = GRPC_TRACER_INITIALIZER(false);
grpc_tracer_flag grpc_flowctl_trace = GRPC_TRACER_INITIALIZER(false); grpc_tracer_flag grpc_flowctl_trace = GRPC_TRACER_INITIALIZER(false);
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_chttp2_refcount = GRPC_TRACER_INITIALIZER(false);
#endif
static const grpc_transport_vtable vtable; static const grpc_transport_vtable vtable;
/* forward declarations of various callbacks that we'll build closures around */ /* forward declarations of various callbacks that we'll build closures around */
@ -91,8 +95,9 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *t,
static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs, static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs,
grpc_error *error); grpc_error *error);
/** Set a transport level setting, and push it to our peer */ /** Set a transport level setting, and push it to our peer */
static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void queue_setting_update(grpc_exec_ctx *exec_ctx,
grpc_chttp2_setting_id id, uint32_t value); grpc_chttp2_transport *t,
grpc_chttp2_setting_id id, uint32_t value);
static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_stream *s, grpc_error *error); grpc_chttp2_stream *s, grpc_error *error);
@ -212,20 +217,26 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
gpr_free(t); gpr_free(t);
} }
#ifdef GRPC_CHTTP2_REFCOUNTING_DEBUG #ifndef NDEBUG
void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx, void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, const char *reason, grpc_chttp2_transport *t, const char *reason,
const char *file, int line) { const char *file, int line) {
gpr_log(GPR_DEBUG, "chttp2:unref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]", t, if (GRPC_TRACER_ON(grpc_trace_chttp2_refcount)) {
t->refs.count, t->refs.count - 1, reason, file, line); gpr_atm val = gpr_atm_no_barrier_load(&t->refs.count);
gpr_log(GPR_DEBUG, "chttp2:unref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]",
t, val, val - 1, reason, file, line);
}
if (!gpr_unref(&t->refs)) return; if (!gpr_unref(&t->refs)) return;
destruct_transport(exec_ctx, t); destruct_transport(exec_ctx, t);
} }
void grpc_chttp2_ref_transport(grpc_chttp2_transport *t, const char *reason, void grpc_chttp2_ref_transport(grpc_chttp2_transport *t, const char *reason,
const char *file, int line) { const char *file, int line) {
gpr_log(GPR_DEBUG, "chttp2: ref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]", t, if (GRPC_TRACER_ON(grpc_trace_chttp2_refcount)) {
t->refs.count, t->refs.count + 1, reason, file, line); gpr_atm val = gpr_atm_no_barrier_load(&t->refs.count);
gpr_log(GPR_DEBUG, "chttp2: ref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]",
t, val, val + 1, reason, file, line);
}
gpr_ref(&t->refs); gpr_ref(&t->refs);
} }
#else #else
@ -342,15 +353,16 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
/* configure http2 the way we like it */ /* configure http2 the way we like it */
if (is_client) { if (is_client) {
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); queue_setting_update(exec_ctx, t,
GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
} }
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
DEFAULT_WINDOW); DEFAULT_WINDOW);
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
DEFAULT_MAX_HEADER_LIST_SIZE); DEFAULT_MAX_HEADER_LIST_SIZE);
push_setting(exec_ctx, t, queue_setting_update(exec_ctx, t,
GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1); GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1);
t->ping_policy = (grpc_chttp2_repeated_ping_policy){ t->ping_policy = (grpc_chttp2_repeated_ping_policy){
.max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA, .max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA,
@ -517,8 +529,8 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
int value = grpc_channel_arg_get_integer( int value = grpc_channel_arg_get_integer(
&channel_args->args[i], settings_map[j].integer_options); &channel_args->args[i], settings_map[j].integer_options);
if (value >= 0) { if (value >= 0) {
push_setting(exec_ctx, t, settings_map[j].setting_id, queue_setting_update(exec_ctx, t, settings_map[j].setting_id,
(uint32_t)value); (uint32_t)value);
} }
} }
break; break;
@ -620,7 +632,7 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_chttp2_stream_ref(grpc_chttp2_stream *s, const char *reason) { void grpc_chttp2_stream_ref(grpc_chttp2_stream *s, const char *reason) {
grpc_stream_ref(s->refcount, reason); grpc_stream_ref(s->refcount, reason);
} }
@ -929,8 +941,11 @@ static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *tp,
GPR_TIMER_END("terminate_writing_with_lock", 0); GPR_TIMER_END("terminate_writing_with_lock", 0);
} }
static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, // Dirties an HTTP2 setting to be sent out next time a writing path occurs.
grpc_chttp2_setting_id id, uint32_t value) { // If the change needs to occur immediately, manually initiate a write.
static void queue_setting_update(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_setting_id id, uint32_t value) {
const grpc_chttp2_setting_parameters *sp = const grpc_chttp2_setting_parameters *sp =
&grpc_chttp2_settings_parameters[id]; &grpc_chttp2_settings_parameters[id];
uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value); uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value);
@ -941,7 +956,6 @@ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
if (use_value != t->settings[GRPC_LOCAL_SETTINGS][id]) { if (use_value != t->settings[GRPC_LOCAL_SETTINGS][id]) {
t->settings[GRPC_LOCAL_SETTINGS][id] = use_value; t->settings[GRPC_LOCAL_SETTINGS][id] = use_value;
t->dirtied_local_settings = 1; t->dirtied_local_settings = 1;
grpc_chttp2_initiate_write(exec_ctx, t, "push_setting");
} }
} }
@ -1403,6 +1417,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
op_payload->recv_initial_metadata.recv_initial_metadata_ready; op_payload->recv_initial_metadata.recv_initial_metadata_ready;
s->recv_initial_metadata = s->recv_initial_metadata =
op_payload->recv_initial_metadata.recv_initial_metadata; op_payload->recv_initial_metadata.recv_initial_metadata;
s->trailing_metadata_available =
op_payload->recv_initial_metadata.trailing_metadata_available;
grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s); grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
} }
@ -2107,8 +2123,8 @@ static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string, gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string,
(int)bdp); (int)bdp);
} }
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
(uint32_t)bdp); (uint32_t)bdp);
} }
static void update_frame(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void update_frame(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@ -2127,8 +2143,8 @@ static void update_frame(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
gpr_log(GPR_DEBUG, "%s: update max_frame size to %d", t->peer_string, gpr_log(GPR_DEBUG, "%s: update max_frame size to %d", t->peer_string,
(int)frame_size); (int)frame_size);
} }
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE, queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
(uint32_t)frame_size); (uint32_t)frame_size);
} }
static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
@ -2726,6 +2742,7 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
gpr_ref_init(&incoming_byte_stream->refs, 2); gpr_ref_init(&incoming_byte_stream->refs, 2);
incoming_byte_stream->transport = t; incoming_byte_stream->transport = t;
incoming_byte_stream->stream = s; incoming_byte_stream->stream = s;
GRPC_ERROR_UNREF(s->byte_stream_error);
s->byte_stream_error = GRPC_ERROR_NONE; s->byte_stream_error = GRPC_ERROR_NONE;
return incoming_byte_stream; return incoming_byte_stream;
} }

@ -26,6 +26,10 @@
extern grpc_tracer_flag grpc_http_trace; extern grpc_tracer_flag grpc_http_trace;
extern grpc_tracer_flag grpc_flowctl_trace; extern grpc_tracer_flag grpc_flowctl_trace;
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_chttp2_refcount;
#endif
grpc_transport *grpc_create_chttp2_transport( grpc_transport *grpc_create_chttp2_transport(
grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args, grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
grpc_endpoint *ep, int is_client); grpc_endpoint *ep, int is_client);

@ -93,7 +93,7 @@ grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx,
(((uint32_t)p->reason_bytes[2]) << 8) | (((uint32_t)p->reason_bytes[2]) << 8) |
(((uint32_t)p->reason_bytes[3])); (((uint32_t)p->reason_bytes[3]));
grpc_error *error = GRPC_ERROR_NONE; grpc_error *error = GRPC_ERROR_NONE;
if (reason != GRPC_HTTP2_NO_ERROR || s->header_frames_received < 2) { if (reason != GRPC_HTTP2_NO_ERROR || s->metadata_buffer[1].size == 0) {
char *message; char *message;
gpr_asprintf(&message, "Received RST_STREAM with error code %d", reason); gpr_asprintf(&message, "Received RST_STREAM with error code %d", reason);
error = grpc_error_set_int( error = grpc_error_set_int(

@ -608,15 +608,14 @@ void grpc_chttp2_hpack_compressor_set_max_table_size(
void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx, void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c, grpc_chttp2_hpack_compressor *c,
grpc_mdelem **extra_headers,
size_t extra_headers_size,
grpc_metadata_batch *metadata, grpc_metadata_batch *metadata,
const grpc_encode_header_options *options, const grpc_encode_header_options *options,
grpc_slice_buffer *outbuf) { grpc_slice_buffer *outbuf) {
framer_state st;
grpc_linked_mdelem *l;
gpr_timespec deadline;
GPR_ASSERT(options->stream_id != 0); GPR_ASSERT(options->stream_id != 0);
framer_state st;
st.seen_regular_header = 0; st.seen_regular_header = 0;
st.stream_id = options->stream_id; st.stream_id = options->stream_id;
st.output = outbuf; st.output = outbuf;
@ -633,11 +632,14 @@ void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx,
if (c->advertise_table_size_change != 0) { if (c->advertise_table_size_change != 0) {
emit_advertise_table_size_change(c, &st); emit_advertise_table_size_change(c, &st);
} }
for (size_t i = 0; i < extra_headers_size; ++i) {
hpack_enc(exec_ctx, c, *extra_headers[i], &st);
}
grpc_metadata_batch_assert_ok(metadata); grpc_metadata_batch_assert_ok(metadata);
for (l = metadata->list.head; l; l = l->next) { for (grpc_linked_mdelem *l = metadata->list.head; l; l = l->next) {
hpack_enc(exec_ctx, c, l->md, &st); hpack_enc(exec_ctx, c, l->md, &st);
} }
deadline = metadata->deadline; gpr_timespec deadline = metadata->deadline;
if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) != 0) { if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) != 0) {
deadline_enc(exec_ctx, c, deadline, &st); deadline_enc(exec_ctx, c, deadline, &st);
} }

@ -85,6 +85,8 @@ typedef struct {
void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx, void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c, grpc_chttp2_hpack_compressor *c,
grpc_mdelem **extra_headers,
size_t extra_headers_size,
grpc_metadata_batch *metadata, grpc_metadata_batch *metadata,
const grpc_encode_header_options *options, const grpc_encode_header_options *options,
grpc_slice_buffer *outbuf); grpc_slice_buffer *outbuf);

@ -447,6 +447,7 @@ struct grpc_chttp2_stream {
grpc_metadata_batch *recv_initial_metadata; grpc_metadata_batch *recv_initial_metadata;
grpc_closure *recv_initial_metadata_ready; grpc_closure *recv_initial_metadata_ready;
bool *trailing_metadata_available;
grpc_byte_stream **recv_message; grpc_byte_stream **recv_message;
grpc_closure *recv_message_ready; grpc_closure *recv_message_ready;
grpc_metadata_batch *recv_trailing_metadata; grpc_metadata_batch *recv_trailing_metadata;
@ -748,7 +749,7 @@ void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx,
void grpc_chttp2_start_writing(grpc_exec_ctx *exec_ctx, void grpc_chttp2_start_writing(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t); grpc_chttp2_transport *t);
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
#define GRPC_CHTTP2_STREAM_REF(stream, reason) \ #define GRPC_CHTTP2_STREAM_REF(stream, reason) \
grpc_chttp2_stream_ref(stream, reason) grpc_chttp2_stream_ref(stream, reason)
#define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream, reason) \ #define GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream, reason) \
@ -764,8 +765,7 @@ void grpc_chttp2_stream_ref(grpc_chttp2_stream *s);
void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s); void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s);
#endif #endif
//#define GRPC_CHTTP2_REFCOUNTING_DEBUG 1 #ifndef NDEBUG
#ifdef GRPC_CHTTP2_REFCOUNTING_DEBUG
#define GRPC_CHTTP2_REF_TRANSPORT(t, r) \ #define GRPC_CHTTP2_REF_TRANSPORT(t, r) \
grpc_chttp2_ref_transport(t, r, __FILE__, __LINE__) grpc_chttp2_ref_transport(t, r, __FILE__, __LINE__)
#define GRPC_CHTTP2_UNREF_TRANSPORT(cl, t, r) \ #define GRPC_CHTTP2_UNREF_TRANSPORT(cl, t, r) \

@ -681,9 +681,19 @@ static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx,
t->parser_data = &t->hpack_parser; t->parser_data = &t->hpack_parser;
switch (s->header_frames_received) { switch (s->header_frames_received) {
case 0: case 0:
t->hpack_parser.on_header = on_initial_header; if (t->is_client && t->header_eof) {
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing Trailers-Only"));
if (s->trailing_metadata_available != NULL) {
*s->trailing_metadata_available = true;
}
t->hpack_parser.on_header = on_trailing_header;
} else {
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing initial_metadata"));
t->hpack_parser.on_header = on_initial_header;
}
break; break;
case 1: case 1:
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing trailing_metadata"));
t->hpack_parser.on_header = on_trailing_header; t->hpack_parser.on_header = on_trailing_header;
break; break;
case 2: case 2:

@ -162,6 +162,20 @@ static uint32_t target_write_size(grpc_chttp2_transport *t) {
return 1024 * 1024; return 1024 * 1024;
} }
// Returns true if initial_metadata contains only default headers.
//
// TODO(roth): The fact that we hard-code these particular headers here
// is fairly ugly. Need some better way to know which headers are
// default, maybe via a bit in the static metadata table?
static bool is_default_initial_metadata(grpc_metadata_batch *initial_metadata) {
int num_default_fields =
(initial_metadata->idx.named.status != NULL) +
(initial_metadata->idx.named.content_type != NULL) +
(initial_metadata->idx.named.grpc_encoding != NULL) +
(initial_metadata->idx.named.grpc_accept_encoding != NULL);
return (size_t)num_default_fields == initial_metadata->list.count;
}
grpc_chttp2_begin_write_result grpc_chttp2_begin_write( grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
grpc_chttp2_stream *s; grpc_chttp2_stream *s;
@ -218,31 +232,59 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
t->is_client ? "CLIENT" : "SERVER", s->id, sent_initial_metadata, t->is_client ? "CLIENT" : "SERVER", s->id, sent_initial_metadata,
s->send_initial_metadata != NULL, s->announce_window)); s->send_initial_metadata != NULL, s->announce_window));
grpc_mdelem *extra_headers_for_trailing_metadata[2];
size_t num_extra_headers_for_trailing_metadata = 0;
/* send initial metadata if it's available */ /* send initial metadata if it's available */
if (!sent_initial_metadata && s->send_initial_metadata) { if (!sent_initial_metadata && s->send_initial_metadata != NULL) {
grpc_encode_header_options hopt = { // We skip this on the server side if there is no custom initial
.stream_id = s->id, // metadata, there are no messages to send, and we are also sending
.is_eof = false, // trailing metadata. This results in a Trailers-Only response,
.use_true_binary_metadata = // which is required for retries, as per:
t->settings // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#when-retries-are-valid
[GRPC_PEER_SETTINGS] if (t->is_client || s->fetching_send_message != NULL ||
[GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] != 0, s->flow_controlled_buffer.length != 0 ||
.max_frame_size = t->settings[GRPC_PEER_SETTINGS] s->send_trailing_metadata == NULL ||
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE], !is_default_initial_metadata(s->send_initial_metadata)) {
.stats = &s->stats.outgoing}; grpc_encode_header_options hopt = {
grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, .stream_id = s->id,
s->send_initial_metadata, &hopt, &t->outbuf); .is_eof = false,
.use_true_binary_metadata =
t->settings
[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] != 0,
.max_frame_size = t->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
.stats = &s->stats.outgoing};
grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, NULL, 0,
s->send_initial_metadata, &hopt, &t->outbuf);
now_writing = true;
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
if (!t->is_client) {
t->ping_recv_state.last_ping_recv_time =
gpr_inf_past(GPR_CLOCK_MONOTONIC);
t->ping_recv_state.ping_strikes = 0;
}
} else {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)"));
// When sending Trailers-Only, we need to move the :status and
// content-type headers to the trailers.
if (s->send_initial_metadata->idx.named.status != NULL) {
extra_headers_for_trailing_metadata
[num_extra_headers_for_trailing_metadata++] =
&s->send_initial_metadata->idx.named.status->md;
}
if (s->send_initial_metadata->idx.named.content_type != NULL) {
extra_headers_for_trailing_metadata
[num_extra_headers_for_trailing_metadata++] =
&s->send_initial_metadata->idx.named.content_type->md;
}
}
s->send_initial_metadata = NULL; s->send_initial_metadata = NULL;
s->sent_initial_metadata = true; s->sent_initial_metadata = true;
sent_initial_metadata = true; sent_initial_metadata = true;
now_writing = true;
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
if (!t->is_client) {
t->ping_recv_state.last_ping_recv_time =
gpr_inf_past(GPR_CLOCK_MONOTONIC);
t->ping_recv_state.ping_strikes = 0;
}
} }
/* send any window updates */ /* send any window updates */
if (s->announce_window > 0) { if (s->announce_window > 0) {
@ -320,6 +362,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
if (s->send_trailing_metadata != NULL && if (s->send_trailing_metadata != NULL &&
s->fetching_send_message == NULL && s->fetching_send_message == NULL &&
s->flow_controlled_buffer.length == 0) { s->flow_controlled_buffer.length == 0) {
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata"));
if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) { if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) {
grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true, grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true,
&s->stats.outgoing, &t->outbuf); &s->stats.outgoing, &t->outbuf);
@ -337,6 +380,8 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE], [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
.stats = &s->stats.outgoing}; .stats = &s->stats.outgoing};
grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor,
extra_headers_for_trailing_metadata,
num_extra_headers_for_trailing_metadata,
s->send_trailing_metadata, &hopt, s->send_trailing_metadata, &hopt,
&t->outbuf); &t->outbuf);
} }

@ -766,20 +766,50 @@ static bool op_can_be_run(grpc_transport_stream_op_batch *curr_op,
bool is_canceled_or_failed = stream_state->state_op_done[OP_CANCEL_ERROR] || bool is_canceled_or_failed = stream_state->state_op_done[OP_CANCEL_ERROR] ||
stream_state->state_callback_received[OP_FAILED]; stream_state->state_callback_received[OP_FAILED];
if (is_canceled_or_failed) { if (is_canceled_or_failed) {
if (op_id == OP_SEND_INITIAL_METADATA) result = false; if (op_id == OP_SEND_INITIAL_METADATA) {
if (op_id == OP_SEND_MESSAGE) result = false; CRONET_LOG(GPR_DEBUG, "Because");
if (op_id == OP_SEND_TRAILING_METADATA) result = false; result = false;
if (op_id == OP_CANCEL_ERROR) result = false; }
if (op_id == OP_SEND_MESSAGE) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
if (op_id == OP_SEND_TRAILING_METADATA) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
if (op_id == OP_CANCEL_ERROR) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
/* already executed */ /* already executed */
if (op_id == OP_RECV_INITIAL_METADATA && if (op_id == OP_RECV_INITIAL_METADATA &&
stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false; result = false;
if (op_id == OP_RECV_MESSAGE && }
stream_state->state_op_done[OP_RECV_MESSAGE]) if (op_id == OP_RECV_MESSAGE && op_state->state_op_done[OP_RECV_MESSAGE]) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false; result = false;
}
if (op_id == OP_RECV_TRAILING_METADATA && if (op_id == OP_RECV_TRAILING_METADATA &&
stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false; result = false;
}
/* ON_COMPLETE can be processed if one of the following conditions is met:
* 1. the stream failed
* 2. the stream is cancelled, and the callback is received
* 3. the stream succeeded before cancel is effective
* 4. the stream is cancelled, and the stream is never started */
if (op_id == OP_ON_COMPLETE &&
!(stream_state->state_callback_received[OP_FAILED] ||
stream_state->state_callback_received[OP_CANCELED] ||
stream_state->state_callback_received[OP_SUCCEEDED] ||
!stream_state->state_op_done[OP_SEND_INITIAL_METADATA])) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
} else if (op_id == OP_SEND_INITIAL_METADATA) { } else if (op_id == OP_SEND_INITIAL_METADATA) {
/* already executed */ /* already executed */
if (stream_state->state_op_done[OP_SEND_INITIAL_METADATA]) result = false; if (stream_state->state_op_done[OP_SEND_INITIAL_METADATA]) result = false;
@ -868,7 +898,7 @@ static bool op_can_be_run(grpc_transport_stream_op_batch *curr_op,
CRONET_LOG(GPR_DEBUG, "Because"); CRONET_LOG(GPR_DEBUG, "Because");
result = false; result = false;
} else if (curr_op->recv_message && } else if (curr_op->recv_message &&
!stream_state->state_op_done[OP_RECV_MESSAGE]) { !op_state->state_op_done[OP_RECV_MESSAGE]) {
CRONET_LOG(GPR_DEBUG, "Because"); CRONET_LOG(GPR_DEBUG, "Because");
result = false; result = false;
} else if (curr_op->cancel_stream && } else if (curr_op->cancel_stream &&
@ -1067,6 +1097,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_op->payload->recv_message.recv_message_ready, stream_op->payload->recv_message.recv_message_ready,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
stream_state->state_op_done[OP_RECV_MESSAGE] = true; stream_state->state_op_done[OP_RECV_MESSAGE] = true;
oas->state.state_op_done[OP_RECV_MESSAGE] = true;
result = ACTION_TAKEN_NO_CALLBACK; result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_state->state_callback_received[OP_FAILED]) { } else if (stream_state->state_callback_received[OP_FAILED]) {
CRONET_LOG(GPR_DEBUG, "Stream failed."); CRONET_LOG(GPR_DEBUG, "Stream failed.");
@ -1074,6 +1105,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_op->payload->recv_message.recv_message_ready, stream_op->payload->recv_message.recv_message_ready,
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
stream_state->state_op_done[OP_RECV_MESSAGE] = true; stream_state->state_op_done[OP_RECV_MESSAGE] = true;
oas->state.state_op_done[OP_RECV_MESSAGE] = true;
result = ACTION_TAKEN_NO_CALLBACK; result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_state->rs.read_stream_closed == true) { } else if (stream_state->rs.read_stream_closed == true) {
/* No more data will be received */ /* No more data will be received */
@ -1214,8 +1246,8 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
} else if (stream_op->cancel_stream && } else if (stream_op->cancel_stream &&
op_can_be_run(stream_op, s, &oas->state, OP_CANCEL_ERROR)) { op_can_be_run(stream_op, s, &oas->state, OP_CANCEL_ERROR)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas); CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas);
CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs);
if (s->cbs) { if (s->cbs) {
CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs);
bidirectional_stream_cancel(s->cbs); bidirectional_stream_cancel(s->cbs);
result = ACTION_TAKEN_WITH_CALLBACK; result = ACTION_TAKEN_WITH_CALLBACK;
} else { } else {

@ -234,7 +234,7 @@ void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
grpc_call_stack *call_stack, grpc_call_stack *call_stack,
grpc_polling_entity *pollent); grpc_polling_entity *pollent);
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
#define GRPC_CALL_STACK_REF(call_stack, reason) \ #define GRPC_CALL_STACK_REF(call_stack, reason) \
grpc_stream_ref(&(call_stack)->refcount, reason) grpc_stream_ref(&(call_stack)->refcount, reason)
#define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \ #define GRPC_CALL_STACK_UNREF(exec_ctx, call_stack, reason) \

@ -25,6 +25,7 @@
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/handshaker_registry.h"
#include "src/core/lib/security/transport/security_handshaker.h" #include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
@ -157,7 +158,6 @@ static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
gpr_timespec deadline, gpr_timespec deadline,
void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg, void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *endpoint)) { grpc_endpoint *endpoint)) {
grpc_channel_security_connector *sc = NULL;
on_done_closure *c = gpr_malloc(sizeof(*c)); on_done_closure *c = gpr_malloc(sizeof(*c));
const char *pem_root_certs = grpc_get_default_ssl_roots(); const char *pem_root_certs = grpc_get_default_ssl_roots();
if (pem_root_certs == NULL) { if (pem_root_certs == NULL) {
@ -168,11 +168,13 @@ static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
} }
c->func = on_done; c->func = on_done;
c->arg = arg; c->arg = arg;
c->handshake_mgr = grpc_handshake_manager_create(); grpc_channel_security_connector *sc = NULL;
GPR_ASSERT(httpcli_ssl_channel_security_connector_create( GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
exec_ctx, pem_root_certs, host, &sc) == GRPC_SECURITY_OK); exec_ctx, pem_root_certs, host, &sc) == GRPC_SECURITY_OK);
grpc_channel_security_connector_add_handshakers(exec_ctx, sc, grpc_arg channel_arg = grpc_security_connector_to_arg(&sc->base);
c->handshake_mgr); grpc_channel_args args = {1, &channel_arg};
c->handshake_mgr = grpc_handshake_manager_create();
grpc_handshakers_add(exec_ctx, HANDSHAKER_CLIENT, &args, c->handshake_mgr);
grpc_handshake_manager_do_handshake( grpc_handshake_manager_do_handshake(
exec_ctx, c->handshake_mgr, tcp, NULL /* channel_args */, deadline, exec_ctx, c->handshake_mgr, tcp, NULL /* channel_args */, deadline,
NULL /* acceptor */, on_handshake_done, c /* user_data */); NULL /* acceptor */, on_handshake_done, c /* user_data */);

@ -24,7 +24,11 @@
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
grpc_tracer_flag grpc_trace_closure = GRPC_TRACER_INITIALIZER(false);
#endif
#ifndef NDEBUG
grpc_closure *grpc_closure_init(const char *file, int line, grpc_closure *grpc_closure_init(const char *file, int line,
grpc_closure *closure, grpc_iomgr_cb_func cb, grpc_closure *closure, grpc_iomgr_cb_func cb,
void *cb_arg, void *cb_arg,
@ -37,7 +41,7 @@ grpc_closure *grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
closure->cb = cb; closure->cb = cb;
closure->cb_arg = cb_arg; closure->cb_arg = cb_arg;
closure->scheduler = scheduler; closure->scheduler = scheduler;
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
closure->scheduled = false; closure->scheduled = false;
closure->file_initiated = NULL; closure->file_initiated = NULL;
closure->line_initiated = 0; closure->line_initiated = 0;
@ -112,7 +116,7 @@ static void closure_wrapper(grpc_exec_ctx *exec_ctx, void *arg,
cb(exec_ctx, cb_arg, error); cb(exec_ctx, cb_arg, error);
} }
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
grpc_closure *grpc_closure_create(const char *file, int line, grpc_closure *grpc_closure_create(const char *file, int line,
grpc_iomgr_cb_func cb, void *cb_arg, grpc_iomgr_cb_func cb, void *cb_arg,
grpc_closure_scheduler *scheduler) { grpc_closure_scheduler *scheduler) {
@ -123,7 +127,7 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg,
wrapped_closure *wc = gpr_malloc(sizeof(*wc)); wrapped_closure *wc = gpr_malloc(sizeof(*wc));
wc->cb = cb; wc->cb = cb;
wc->cb_arg = cb_arg; wc->cb_arg = cb_arg;
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
grpc_closure_init(file, line, &wc->wrapper, closure_wrapper, wc, scheduler); grpc_closure_init(file, line, &wc->wrapper, closure_wrapper, wc, scheduler);
#else #else
grpc_closure_init(&wc->wrapper, closure_wrapper, wc, scheduler); grpc_closure_init(&wc->wrapper, closure_wrapper, wc, scheduler);
@ -131,7 +135,7 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg,
return &wc->wrapper; return &wc->wrapper;
} }
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
void grpc_closure_run(const char *file, int line, grpc_exec_ctx *exec_ctx, void grpc_closure_run(const char *file, int line, grpc_exec_ctx *exec_ctx,
grpc_closure *c, grpc_error *error) { grpc_closure *c, grpc_error *error) {
#else #else
@ -140,7 +144,7 @@ void grpc_closure_run(grpc_exec_ctx *exec_ctx, grpc_closure *c,
#endif #endif
GPR_TIMER_BEGIN("grpc_closure_run", 0); GPR_TIMER_BEGIN("grpc_closure_run", 0);
if (c != NULL) { if (c != NULL) {
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
c->file_initiated = file; c->file_initiated = file;
c->line_initiated = line; c->line_initiated = line;
c->run = true; c->run = true;
@ -153,7 +157,7 @@ void grpc_closure_run(grpc_exec_ctx *exec_ctx, grpc_closure *c,
GPR_TIMER_END("grpc_closure_run", 0); GPR_TIMER_END("grpc_closure_run", 0);
} }
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
void grpc_closure_sched(const char *file, int line, grpc_exec_ctx *exec_ctx, void grpc_closure_sched(const char *file, int line, grpc_exec_ctx *exec_ctx,
grpc_closure *c, grpc_error *error) { grpc_closure *c, grpc_error *error) {
#else #else
@ -162,7 +166,7 @@ void grpc_closure_sched(grpc_exec_ctx *exec_ctx, grpc_closure *c,
#endif #endif
GPR_TIMER_BEGIN("grpc_closure_sched", 0); GPR_TIMER_BEGIN("grpc_closure_sched", 0);
if (c != NULL) { if (c != NULL) {
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
GPR_ASSERT(!c->scheduled); GPR_ASSERT(!c->scheduled);
c->scheduled = true; c->scheduled = true;
c->file_initiated = file; c->file_initiated = file;
@ -177,7 +181,7 @@ void grpc_closure_sched(grpc_exec_ctx *exec_ctx, grpc_closure *c,
GPR_TIMER_END("grpc_closure_sched", 0); GPR_TIMER_END("grpc_closure_sched", 0);
} }
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
void grpc_closure_list_sched(const char *file, int line, void grpc_closure_list_sched(const char *file, int line,
grpc_exec_ctx *exec_ctx, grpc_closure_list *list) { grpc_exec_ctx *exec_ctx, grpc_closure_list *list) {
#else #else
@ -186,7 +190,7 @@ void grpc_closure_list_sched(grpc_exec_ctx *exec_ctx, grpc_closure_list *list) {
grpc_closure *c = list->head; grpc_closure *c = list->head;
while (c != NULL) { while (c != NULL) {
grpc_closure *next = c->next_data.next; grpc_closure *next = c->next_data.next;
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
GPR_ASSERT(!c->scheduled); GPR_ASSERT(!c->scheduled);
c->scheduled = true; c->scheduled = true;
c->file_initiated = file; c->file_initiated = file;

@ -26,9 +26,17 @@
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
#include "src/core/lib/support/mpscq.h" #include "src/core/lib/support/mpscq.h"
#ifdef __cplusplus
extern "C" {
#endif
struct grpc_closure; struct grpc_closure;
typedef struct grpc_closure grpc_closure; typedef struct grpc_closure grpc_closure;
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_closure;
#endif
typedef struct grpc_closure_list { typedef struct grpc_closure_list {
grpc_closure *head; grpc_closure *head;
grpc_closure *tail; grpc_closure *tail;
@ -38,7 +46,9 @@ typedef struct grpc_closure_list {
* *
* \param arg Arbitrary input. * \param arg Arbitrary input.
* \param error GRPC_ERROR_NONE if no error occurred, otherwise some grpc_error * \param error GRPC_ERROR_NONE if no error occurred, otherwise some grpc_error
* describing what went wrong */ * describing what went wrong.
* Error contract: it is not the cb's job to unref this error;
* the closure scheduler will do that after the cb returns */
typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg, typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error); grpc_error *error);
@ -59,8 +69,6 @@ struct grpc_closure_scheduler {
const grpc_closure_scheduler_vtable *vtable; const grpc_closure_scheduler_vtable *vtable;
}; };
// #define GRPC_CLOSURE_RICH_DEBUG
/** A closure over a grpc_iomgr_cb_func. */ /** A closure over a grpc_iomgr_cb_func. */
struct grpc_closure { struct grpc_closure {
/** Once queued, next indicates the next queued closure; before then, scratch /** Once queued, next indicates the next queued closure; before then, scratch
@ -89,7 +97,7 @@ struct grpc_closure {
// extra tracing and debugging for grpc_closure. This incurs a decent amount of // extra tracing and debugging for grpc_closure. This incurs a decent amount of
// overhead per closure, so it must be enabled at compile time. // overhead per closure, so it must be enabled at compile time.
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
bool scheduled; bool scheduled;
bool run; // true = run, false = scheduled bool run; // true = run, false = scheduled
const char *file_created; const char *file_created;
@ -100,7 +108,7 @@ struct grpc_closure {
}; };
/** Initializes \a closure with \a cb and \a cb_arg. Returns \a closure. */ /** Initializes \a closure with \a cb and \a cb_arg. Returns \a closure. */
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
grpc_closure *grpc_closure_init(const char *file, int line, grpc_closure *grpc_closure_init(const char *file, int line,
grpc_closure *closure, grpc_iomgr_cb_func cb, grpc_closure *closure, grpc_iomgr_cb_func cb,
void *cb_arg, void *cb_arg,
@ -116,7 +124,7 @@ grpc_closure *grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
#endif #endif
/* Create a heap allocated closure: try to avoid except for very rare events */ /* Create a heap allocated closure: try to avoid except for very rare events */
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
grpc_closure *grpc_closure_create(const char *file, int line, grpc_closure *grpc_closure_create(const char *file, int line,
grpc_iomgr_cb_func cb, void *cb_arg, grpc_iomgr_cb_func cb, void *cb_arg,
grpc_closure_scheduler *scheduler); grpc_closure_scheduler *scheduler);
@ -153,7 +161,7 @@ bool grpc_closure_list_empty(grpc_closure_list list);
/** Run a closure directly. Caller ensures that no locks are being held above. /** Run a closure directly. Caller ensures that no locks are being held above.
* Note that calling this at the end of a closure callback function itself is * Note that calling this at the end of a closure callback function itself is
* by definition safe. */ * by definition safe. */
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
void grpc_closure_run(const char *file, int line, grpc_exec_ctx *exec_ctx, void grpc_closure_run(const char *file, int line, grpc_exec_ctx *exec_ctx,
grpc_closure *closure, grpc_error *error); grpc_closure *closure, grpc_error *error);
#define GRPC_CLOSURE_RUN(exec_ctx, closure, error) \ #define GRPC_CLOSURE_RUN(exec_ctx, closure, error) \
@ -166,7 +174,7 @@ void grpc_closure_run(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
#endif #endif
/** Schedule a closure to be run. Does not need to be run from a safe point. */ /** Schedule a closure to be run. Does not need to be run from a safe point. */
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
void grpc_closure_sched(const char *file, int line, grpc_exec_ctx *exec_ctx, void grpc_closure_sched(const char *file, int line, grpc_exec_ctx *exec_ctx,
grpc_closure *closure, grpc_error *error); grpc_closure *closure, grpc_error *error);
#define GRPC_CLOSURE_SCHED(exec_ctx, closure, error) \ #define GRPC_CLOSURE_SCHED(exec_ctx, closure, error) \
@ -180,7 +188,7 @@ void grpc_closure_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
/** Schedule all closures in a list to be run. Does not need to be run from a /** Schedule all closures in a list to be run. Does not need to be run from a
* safe point. */ * safe point. */
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
void grpc_closure_list_sched(const char *file, int line, void grpc_closure_list_sched(const char *file, int line,
grpc_exec_ctx *exec_ctx, grpc_exec_ctx *exec_ctx,
grpc_closure_list *closure_list); grpc_closure_list *closure_list);
@ -193,4 +201,8 @@ void grpc_closure_list_sched(grpc_exec_ctx *exec_ctx,
grpc_closure_list_sched(exec_ctx, closure_list) grpc_closure_list_sched(exec_ctx, closure_list)
#endif #endif
#ifdef __cplusplus
}
#endif
#endif /* GRPC_CORE_LIB_IOMGR_CLOSURE_H */ #endif /* GRPC_CORE_LIB_IOMGR_CLOSURE_H */

@ -102,12 +102,14 @@ static void start_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
} }
} }
#ifdef GRPC_COMBINER_REFCOUNT_DEBUG #ifndef NDEBUG
#define GRPC_COMBINER_DEBUG_SPAM(op, delta) \ #define GRPC_COMBINER_DEBUG_SPAM(op, delta) \
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, \ if (GRPC_TRACER_ON(grpc_combiner_trace)) { \
"combiner[%p] %s %" PRIdPTR " --> %" PRIdPTR " %s", lock, (op), \ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, \
gpr_atm_no_barrier_load(&lock->refs.count), \ "C:%p %s %" PRIdPTR " --> %" PRIdPTR " %s", lock, (op), \
gpr_atm_no_barrier_load(&lock->refs.count) + (delta), reason); gpr_atm_no_barrier_load(&lock->refs.count), \
gpr_atm_no_barrier_load(&lock->refs.count) + (delta), reason); \
}
#else #else
#define GRPC_COMBINER_DEBUG_SPAM(op, delta) #define GRPC_COMBINER_DEBUG_SPAM(op, delta)
#endif #endif
@ -247,7 +249,7 @@ bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx) {
GPR_TIMER_BEGIN("combiner.exec1", 0); GPR_TIMER_BEGIN("combiner.exec1", 0);
grpc_closure *cl = (grpc_closure *)n; grpc_closure *cl = (grpc_closure *)n;
grpc_error *cl_err = cl->error_data.error; grpc_error *cl_err = cl->error_data.error;
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
cl->scheduled = false; cl->scheduled = false;
#endif #endif
cl->cb(exec_ctx, cl->cb_arg, cl_err); cl->cb(exec_ctx, cl->cb_arg, cl_err);
@ -264,7 +266,7 @@ bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx) {
gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c)); gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c));
grpc_closure *next = c->next_data.next; grpc_closure *next = c->next_data.next;
grpc_error *error = c->error_data.error; grpc_error *error = c->error_data.error;
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
c->scheduled = false; c->scheduled = false;
#endif #endif
c->cb(exec_ctx, c->cb_arg, error); c->cb(exec_ctx, c->cb_arg, error);

@ -35,8 +35,7 @@
// necessary // necessary
grpc_combiner *grpc_combiner_create(void); grpc_combiner *grpc_combiner_create(void);
//#define GRPC_COMBINER_REFCOUNT_DEBUG #ifndef NDEBUG
#ifdef GRPC_COMBINER_REFCOUNT_DEBUG
#define GRPC_COMBINER_DEBUG_ARGS \ #define GRPC_COMBINER_DEBUG_ARGS \
, const char *file, int line, const char *reason , const char *file, int line, const char *reason
#define GRPC_COMBINER_REF(combiner, reason) \ #define GRPC_COMBINER_REF(combiner, reason) \

@ -30,10 +30,15 @@
#include <grpc/support/log_windows.h> #include <grpc/support/log_windows.h>
#endif #endif
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/error_internal.h" #include "src/core/lib/iomgr/error_internal.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_error_refcount = GRPC_TRACER_INITIALIZER(false);
#endif
static const char *error_int_name(grpc_error_ints key) { static const char *error_int_name(grpc_error_ints key) {
switch (key) { switch (key) {
case GRPC_ERROR_INT_ERRNO: case GRPC_ERROR_INT_ERRNO:
@ -119,14 +124,14 @@ bool grpc_error_is_special(grpc_error *err) {
err == GRPC_ERROR_CANCELLED; err == GRPC_ERROR_CANCELLED;
} }
#ifdef GRPC_ERROR_REFCOUNT_DEBUG #ifndef NDEBUG
grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line, grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line) {
const char *func) {
if (grpc_error_is_special(err)) return err; if (grpc_error_is_special(err)) return err;
gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err, if (GRPC_TRACER_ON(grpc_trace_error_refcount)) {
gpr_atm_no_barrier_load(&err->atomics.refs.count), gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d]", err,
gpr_atm_no_barrier_load(&err->atomics.refs.count) + 1, file, line, gpr_atm_no_barrier_load(&err->atomics.refs.count),
func); gpr_atm_no_barrier_load(&err->atomics.refs.count) + 1, file, line);
}
gpr_ref(&err->atomics.refs); gpr_ref(&err->atomics.refs);
return err; return err;
} }
@ -172,14 +177,14 @@ static void error_destroy(grpc_error *err) {
gpr_free(err); gpr_free(err);
} }
#ifdef GRPC_ERROR_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_error_unref(grpc_error *err, const char *file, int line, void grpc_error_unref(grpc_error *err, const char *file, int line) {
const char *func) {
if (grpc_error_is_special(err)) return; if (grpc_error_is_special(err)) return;
gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", err, if (GRPC_TRACER_ON(grpc_trace_error_refcount)) {
gpr_atm_no_barrier_load(&err->atomics.refs.count), gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d]", err,
gpr_atm_no_barrier_load(&err->atomics.refs.count) - 1, file, line, gpr_atm_no_barrier_load(&err->atomics.refs.count),
func); gpr_atm_no_barrier_load(&err->atomics.refs.count) - 1, file, line);
}
if (gpr_unref(&err->atomics.refs)) { if (gpr_unref(&err->atomics.refs)) {
error_destroy(err); error_destroy(err);
} }
@ -202,13 +207,17 @@ static uint8_t get_placement(grpc_error **err, size_t size) {
if ((*err)->arena_size + slots > (*err)->arena_capacity) { if ((*err)->arena_size + slots > (*err)->arena_capacity) {
return UINT8_MAX; return UINT8_MAX;
} }
#ifdef GRPC_ERROR_REFCOUNT_DEBUG #ifndef NDEBUG
grpc_error *orig = *err; grpc_error *orig = *err;
#endif #endif
*err = gpr_realloc( *err = gpr_realloc(
*err, sizeof(grpc_error) + (*err)->arena_capacity * sizeof(intptr_t)); *err, sizeof(grpc_error) + (*err)->arena_capacity * sizeof(intptr_t));
#ifdef GRPC_ERROR_REFCOUNT_DEBUG #ifndef NDEBUG
if (*err != orig) gpr_log(GPR_DEBUG, "realloc %p -> %p", orig, *err); if (GRPC_TRACER_ON(grpc_trace_error_refcount)) {
if (*err != orig) {
gpr_log(GPR_DEBUG, "realloc %p -> %p", orig, *err);
}
}
#endif #endif
} }
uint8_t placement = (*err)->arena_size; uint8_t placement = (*err)->arena_size;
@ -316,8 +325,10 @@ grpc_error *grpc_error_create(const char *file, int line, grpc_slice desc,
if (err == NULL) { // TODO(ctiller): make gpr_malloc return NULL if (err == NULL) { // TODO(ctiller): make gpr_malloc return NULL
return GRPC_ERROR_OOM; return GRPC_ERROR_OOM;
} }
#ifdef GRPC_ERROR_REFCOUNT_DEBUG #ifndef NDEBUG
gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line); if (GRPC_TRACER_ON(grpc_trace_error_refcount)) {
gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line);
}
#endif #endif
err->arena_size = 0; err->arena_size = 0;
@ -395,8 +406,10 @@ static grpc_error *copy_error_and_unref(grpc_error *in) {
new_arena_capacity = (uint8_t)(3 * new_arena_capacity / 2); new_arena_capacity = (uint8_t)(3 * new_arena_capacity / 2);
} }
out = gpr_malloc(sizeof(*in) + new_arena_capacity * sizeof(intptr_t)); out = gpr_malloc(sizeof(*in) + new_arena_capacity * sizeof(intptr_t));
#ifdef GRPC_ERROR_REFCOUNT_DEBUG #ifndef NDEBUG
gpr_log(GPR_DEBUG, "%p create copying %p", out, in); if (GRPC_TRACER_ON(grpc_trace_error_refcount)) {
gpr_log(GPR_DEBUG, "%p create copying %p", out, in);
}
#endif #endif
// bulk memcpy of the rest of the struct. // bulk memcpy of the rest of the struct.
size_t skip = sizeof(&out->atomics); size_t skip = sizeof(&out->atomics);

@ -26,6 +26,8 @@
#include <grpc/status.h> #include <grpc/status.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "src/core/lib/debug/trace.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -36,6 +38,10 @@ extern "C" {
typedef struct grpc_error grpc_error; typedef struct grpc_error grpc_error;
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_error_refcount;
#endif
typedef enum { typedef enum {
/// 'errno' from the operating system /// 'errno' from the operating system
GRPC_ERROR_INT_ERRNO, GRPC_ERROR_INT_ERRNO,
@ -149,15 +155,11 @@ grpc_error *grpc_error_create(const char *file, int line, grpc_slice desc,
grpc_error_create(__FILE__, __LINE__, grpc_slice_from_copied_string(desc), \ grpc_error_create(__FILE__, __LINE__, grpc_slice_from_copied_string(desc), \
errs, count) errs, count)
// #define GRPC_ERROR_REFCOUNT_DEBUG #ifndef NDEBUG
#ifdef GRPC_ERROR_REFCOUNT_DEBUG grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line);
grpc_error *grpc_error_ref(grpc_error *err, const char *file, int line, void grpc_error_unref(grpc_error *err, const char *file, int line);
const char *func); #define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__)
void grpc_error_unref(grpc_error *err, const char *file, int line, #define GRPC_ERROR_UNREF(err) grpc_error_unref(err, __FILE__, __LINE__)
const char *func);
#define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__, __func__)
#define GRPC_ERROR_UNREF(err) \
grpc_error_unref(err, __FILE__, __LINE__, __func__)
#else #else
grpc_error *grpc_error_ref(grpc_error *err); grpc_error *grpc_error_ref(grpc_error *err);
void grpc_error_unref(grpc_error *err); void grpc_error_unref(grpc_error *err);

@ -194,8 +194,10 @@ static grpc_fd *fd_create(int fd, const char *name) {
char *fd_name; char *fd_name;
gpr_asprintf(&fd_name, "%s fd=%d", name, fd); gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name); if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name);
}
#endif #endif
gpr_free(fd_name); gpr_free(fd_name);

@ -147,8 +147,7 @@ struct grpc_fd {
}; };
/* Reference counting for fds */ /* Reference counting for fds */
// #define GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
#ifdef GRPC_FD_REF_COUNT_DEBUG
static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line); static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line);
static void fd_unref(grpc_fd *fd, const char *reason, const char *file, static void fd_unref(grpc_fd *fd, const char *reason, const char *file,
int line); int line);
@ -168,20 +167,18 @@ static void fd_global_shutdown(void);
* Polling island Declarations * Polling island Declarations
*/ */
//#define PI_REFCOUNT_DEBUG #ifndef NDEBUG
#ifdef PI_REFCOUNT_DEBUG
#define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__) #define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__)
#define PI_UNREF(exec_ctx, p, r) \ #define PI_UNREF(exec_ctx, p, r) \
pi_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__) pi_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__)
#else /* defined(PI_REFCOUNT_DEBUG) */ #else
#define PI_ADD_REF(p, r) pi_add_ref((p)) #define PI_ADD_REF(p, r) pi_add_ref((p))
#define PI_UNREF(exec_ctx, p, r) pi_unref((exec_ctx), (p)) #define PI_UNREF(exec_ctx, p, r) pi_unref((exec_ctx), (p))
#endif /* !defined(GRPC_PI_REF_COUNT_DEBUG) */ #endif
typedef struct worker_node { typedef struct worker_node {
struct worker_node *next; struct worker_node *next;
@ -313,21 +310,27 @@ gpr_atm g_epoll_sync;
static void pi_add_ref(polling_island *pi); static void pi_add_ref(polling_island *pi);
static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi); static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi);
#ifdef PI_REFCOUNT_DEBUG #ifndef NDEBUG
static void pi_add_ref_dbg(polling_island *pi, const char *reason, static void pi_add_ref_dbg(polling_island *pi, const char *reason,
const char *file, int line) { const char *file, int line) {
long old_cnt = gpr_atm_acq_load(&pi->ref_count); if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
gpr_log(GPR_DEBUG, "Add ref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
" (%s) - (%s, %d)",
pi, old_cnt, old_cnt + 1, reason, file, line);
}
pi_add_ref(pi); pi_add_ref(pi);
gpr_log(GPR_DEBUG, "Add ref pi: %p, old: %ld -> new:%ld (%s) - (%s, %d)",
(void *)pi, old_cnt, old_cnt + 1, reason, file, line);
} }
static void pi_unref_dbg(grpc_exec_ctx *exec_ctx, polling_island *pi, static void pi_unref_dbg(grpc_exec_ctx *exec_ctx, polling_island *pi,
const char *reason, const char *file, int line) { const char *reason, const char *file, int line) {
long old_cnt = gpr_atm_acq_load(&pi->ref_count); if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
gpr_log(GPR_DEBUG, "Unref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
" (%s) - (%s, %d)",
pi, old_cnt, (old_cnt - 1), reason, file, line);
}
pi_unref(exec_ctx, pi); pi_unref(exec_ctx, pi);
gpr_log(GPR_DEBUG, "Unref pi: %p, old:%ld -> new:%ld (%s) - (%s, %d)",
(void *)pi, old_cnt, (old_cnt - 1), reason, file, line);
} }
#endif #endif
@ -792,14 +795,17 @@ static void polling_island_global_shutdown() {
static grpc_fd *fd_freelist = NULL; static grpc_fd *fd_freelist = NULL;
static gpr_mu fd_freelist_mu; static gpr_mu fd_freelist_mu;
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) #define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__)
#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) #define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__)
static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) { int line) {
gpr_log(GPR_DEBUG, "FD %d %p ref %d %ld -> %ld [%s; %s:%d]", fd->fd, if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
(void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), gpr_log(GPR_DEBUG,
gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); "FD %d %p ref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
}
#else #else
#define REF_BY(fd, n, reason) ref_by(fd, n) #define REF_BY(fd, n, reason) ref_by(fd, n)
#define UNREF_BY(fd, n, reason) unref_by(fd, n) #define UNREF_BY(fd, n, reason) unref_by(fd, n)
@ -808,18 +814,19 @@ static void ref_by(grpc_fd *fd, int n) {
GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0);
} }
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) { int line) {
gpr_atm old; if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
gpr_log(GPR_DEBUG, "FD %d %p unref %d %ld -> %ld [%s; %s:%d]", fd->fd, gpr_log(GPR_DEBUG,
(void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), "FD %d %p unref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
}
#else #else
static void unref_by(grpc_fd *fd, int n) { static void unref_by(grpc_fd *fd, int n) {
gpr_atm old;
#endif #endif
old = gpr_atm_full_fetch_add(&fd->refst, -n); gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n);
if (old == n) { if (old == n) {
/* Add the fd to the freelist */ /* Add the fd to the freelist */
gpr_mu_lock(&fd_freelist_mu); gpr_mu_lock(&fd_freelist_mu);
@ -837,7 +844,7 @@ static void unref_by(grpc_fd *fd, int n) {
} }
/* Increment refcount by two to avoid changing the orphan bit */ /* Increment refcount by two to avoid changing the orphan bit */
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
static void fd_ref(grpc_fd *fd, const char *reason, const char *file, static void fd_ref(grpc_fd *fd, const char *reason, const char *file,
int line) { int line) {
ref_by(fd, 2, reason, file, line); ref_by(fd, 2, reason, file, line);
@ -905,8 +912,10 @@ static grpc_fd *fd_create(int fd, const char *name) {
char *fd_name; char *fd_name;
gpr_asprintf(&fd_name, "%s fd=%d", name, fd); gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name); if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name);
}
#endif #endif
gpr_free(fd_name); gpr_free(fd_name);
return new_fd; return new_fd;

@ -93,20 +93,18 @@ static void fd_global_shutdown(void);
* epoll set Declarations * epoll set Declarations
*/ */
//#define EPS_REFCOUNT_DEBUG #ifndef NDEBUG
#ifdef EPS_REFCOUNT_DEBUG
#define EPS_ADD_REF(p, r) eps_add_ref_dbg((p), (r), __FILE__, __LINE__) #define EPS_ADD_REF(p, r) eps_add_ref_dbg((p), (r), __FILE__, __LINE__)
#define EPS_UNREF(exec_ctx, p, r) \ #define EPS_UNREF(exec_ctx, p, r) \
eps_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__) eps_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__)
#else /* defined(EPS_REFCOUNT_DEBUG) */ #else
#define EPS_ADD_REF(p, r) eps_add_ref((p)) #define EPS_ADD_REF(p, r) eps_add_ref((p))
#define EPS_UNREF(exec_ctx, p, r) eps_unref((exec_ctx), (p)) #define EPS_UNREF(exec_ctx, p, r) eps_unref((exec_ctx), (p))
#endif /* !defined(GRPC_EPS_REF_COUNT_DEBUG) */ #endif
typedef struct epoll_set { typedef struct epoll_set {
/* Mutex poller should acquire to poll this. This enforces that only one /* Mutex poller should acquire to poll this. This enforces that only one
@ -226,21 +224,27 @@ gpr_atm g_epoll_sync;
static void eps_add_ref(epoll_set *eps); static void eps_add_ref(epoll_set *eps);
static void eps_unref(grpc_exec_ctx *exec_ctx, epoll_set *eps); static void eps_unref(grpc_exec_ctx *exec_ctx, epoll_set *eps);
#ifdef EPS_REFCOUNT_DEBUG #ifndef NDEBUG
static void eps_add_ref_dbg(epoll_set *eps, const char *reason, static void eps_add_ref_dbg(epoll_set *eps, const char *reason,
const char *file, int line) { const char *file, int line) {
long old_cnt = gpr_atm_acq_load(&eps->ref_count); if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_atm old_cnt = gpr_atm_acq_load(&eps->ref_count);
gpr_log(GPR_DEBUG, "Add ref eps: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
" (%s) - (%s, %d)",
eps, old_cnt, old_cnt + 1, reason, file, line);
}
eps_add_ref(eps); eps_add_ref(eps);
gpr_log(GPR_DEBUG, "Add ref eps: %p, old: %ld -> new:%ld (%s) - (%s, %d)",
(void *)eps, old_cnt, old_cnt + 1, reason, file, line);
} }
static void eps_unref_dbg(grpc_exec_ctx *exec_ctx, epoll_set *eps, static void eps_unref_dbg(grpc_exec_ctx *exec_ctx, epoll_set *eps,
const char *reason, const char *file, int line) { const char *reason, const char *file, int line) {
long old_cnt = gpr_atm_acq_load(&eps->ref_count); if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_atm old_cnt = gpr_atm_acq_load(&eps->ref_count);
gpr_log(GPR_DEBUG, "Unref eps: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
" (%s) - (%s, %d)",
eps, old_cnt, (old_cnt - 1), reason, file, line);
}
eps_unref(exec_ctx, eps); eps_unref(exec_ctx, eps);
gpr_log(GPR_DEBUG, "Unref eps: %p, old:%ld -> new:%ld (%s) - (%s, %d)",
(void *)eps, old_cnt, (old_cnt - 1), reason, file, line);
} }
#endif #endif

@ -231,15 +231,18 @@ static bool append_error(grpc_error **composite, grpc_error *error,
static grpc_fd *fd_freelist = NULL; static grpc_fd *fd_freelist = NULL;
static gpr_mu fd_freelist_mu; static gpr_mu fd_freelist_mu;
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) #define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__)
#define UNREF_BY(ec, fd, n, reason) \ #define UNREF_BY(ec, fd, n, reason) \
unref_by(ec, fd, n, reason, __FILE__, __LINE__) unref_by(ec, fd, n, reason, __FILE__, __LINE__)
static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) { int line) {
gpr_log(GPR_DEBUG, "FD %d %p ref %d %ld -> %ld [%s; %s:%d]", fd->fd, if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
(void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), gpr_log(GPR_DEBUG,
gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); "FD %d %p ref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
}
#else #else
#define REF_BY(fd, n, reason) ref_by(fd, n) #define REF_BY(fd, n, reason) ref_by(fd, n)
#define UNREF_BY(ec, fd, n, reason) unref_by(ec, fd, n) #define UNREF_BY(ec, fd, n, reason) unref_by(ec, fd, n)
@ -264,18 +267,19 @@ static void fd_destroy(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
gpr_mu_unlock(&fd_freelist_mu); gpr_mu_unlock(&fd_freelist_mu);
} }
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n, static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n,
const char *reason, const char *file, int line) { const char *reason, const char *file, int line) {
gpr_atm old; if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
gpr_log(GPR_DEBUG, "FD %d %p unref %d %ld -> %ld [%s; %s:%d]", fd->fd, gpr_log(GPR_DEBUG,
(void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), "FD %d %p unref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
}
#else #else
static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n) { static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n) {
gpr_atm old;
#endif #endif
old = gpr_atm_full_fetch_add(&fd->refst, -n); gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n);
if (old == n) { if (old == n) {
GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_CREATE(fd_destroy, fd, GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_CREATE(fd_destroy, fd,
grpc_schedule_on_exec_ctx), grpc_schedule_on_exec_ctx),
@ -328,8 +332,10 @@ static grpc_fd *fd_create(int fd, const char *name) {
char *fd_name; char *fd_name;
gpr_asprintf(&fd_name, "%s fd=%d", name, fd); gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name); if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name);
}
#endif #endif
gpr_free(fd_name); gpr_free(fd_name);
return new_fd; return new_fd;

@ -140,8 +140,7 @@ struct grpc_fd {
}; };
/* Reference counting for fds */ /* Reference counting for fds */
// #define GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
#ifdef GRPC_FD_REF_COUNT_DEBUG
static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line); static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line);
static void fd_unref(grpc_fd *fd, const char *reason, const char *file, static void fd_unref(grpc_fd *fd, const char *reason, const char *file,
int line); int line);
@ -161,20 +160,18 @@ static void fd_global_shutdown(void);
* Polling island Declarations * Polling island Declarations
*/ */
//#define PI_REFCOUNT_DEBUG #ifndef NDEBUG
#ifdef PI_REFCOUNT_DEBUG
#define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__) #define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__)
#define PI_UNREF(exec_ctx, p, r) \ #define PI_UNREF(exec_ctx, p, r) \
pi_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__) pi_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__)
#else /* defined(GRPC_WORKQUEUE_REFCOUNT_DEBUG) */ #else
#define PI_ADD_REF(p, r) pi_add_ref((p)) #define PI_ADD_REF(p, r) pi_add_ref((p))
#define PI_UNREF(exec_ctx, p, r) pi_unref((exec_ctx), (p)) #define PI_UNREF(exec_ctx, p, r) pi_unref((exec_ctx), (p))
#endif /* !defined(GRPC_PI_REF_COUNT_DEBUG) */ #endif
/* This is also used as grpc_workqueue (by directly casing it) */ /* This is also used as grpc_workqueue (by directly casing it) */
typedef struct polling_island { typedef struct polling_island {
@ -287,21 +284,27 @@ gpr_atm g_epoll_sync;
static void pi_add_ref(polling_island *pi); static void pi_add_ref(polling_island *pi);
static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi); static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi);
#ifdef PI_REFCOUNT_DEBUG #ifndef NDEBUG
static void pi_add_ref_dbg(polling_island *pi, const char *reason, static void pi_add_ref_dbg(polling_island *pi, const char *reason,
const char *file, int line) { const char *file, int line) {
long old_cnt = gpr_atm_acq_load(&pi->ref_count); if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
gpr_log(GPR_DEBUG, "Add ref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
" (%s) - (%s, %d)",
pi, old_cnt, old_cnt + 1, reason, file, line);
}
pi_add_ref(pi); pi_add_ref(pi);
gpr_log(GPR_DEBUG, "Add ref pi: %p, old: %ld -> new:%ld (%s) - (%s, %d)",
(void *)pi, old_cnt, old_cnt + 1, reason, file, line);
} }
static void pi_unref_dbg(grpc_exec_ctx *exec_ctx, polling_island *pi, static void pi_unref_dbg(grpc_exec_ctx *exec_ctx, polling_island *pi,
const char *reason, const char *file, int line) { const char *reason, const char *file, int line) {
long old_cnt = gpr_atm_acq_load(&pi->ref_count); if (GRPC_TRACER_ON(grpc_polling_trace)) {
gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
gpr_log(GPR_DEBUG, "Unref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
" (%s) - (%s, %d)",
pi, old_cnt, (old_cnt - 1), reason, file, line);
}
pi_unref(exec_ctx, pi); pi_unref(exec_ctx, pi);
gpr_log(GPR_DEBUG, "Unref pi: %p, old:%ld -> new:%ld (%s) - (%s, %d)",
(void *)pi, old_cnt, (old_cnt - 1), reason, file, line);
} }
#endif #endif
@ -720,14 +723,17 @@ static void polling_island_global_shutdown() {
static grpc_fd *fd_freelist = NULL; static grpc_fd *fd_freelist = NULL;
static gpr_mu fd_freelist_mu; static gpr_mu fd_freelist_mu;
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) #define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__)
#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) #define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__)
static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) { int line) {
gpr_log(GPR_DEBUG, "FD %d %p ref %d %ld -> %ld [%s; %s:%d]", fd->fd, if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
(void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), gpr_log(GPR_DEBUG,
gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); "FD %d %p ref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
}
#else #else
#define REF_BY(fd, n, reason) ref_by(fd, n) #define REF_BY(fd, n, reason) ref_by(fd, n)
#define UNREF_BY(fd, n, reason) unref_by(fd, n) #define UNREF_BY(fd, n, reason) unref_by(fd, n)
@ -736,18 +742,19 @@ static void ref_by(grpc_fd *fd, int n) {
GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0);
} }
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) { int line) {
gpr_atm old; if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
gpr_log(GPR_DEBUG, "FD %d %p unref %d %ld -> %ld [%s; %s:%d]", fd->fd, gpr_log(GPR_DEBUG,
(void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), "FD %d %p unref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
}
#else #else
static void unref_by(grpc_fd *fd, int n) { static void unref_by(grpc_fd *fd, int n) {
gpr_atm old;
#endif #endif
old = gpr_atm_full_fetch_add(&fd->refst, -n); gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n);
if (old == n) { if (old == n) {
/* Add the fd to the freelist */ /* Add the fd to the freelist */
gpr_mu_lock(&fd_freelist_mu); gpr_mu_lock(&fd_freelist_mu);
@ -765,7 +772,7 @@ static void unref_by(grpc_fd *fd, int n) {
} }
/* Increment refcount by two to avoid changing the orphan bit */ /* Increment refcount by two to avoid changing the orphan bit */
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
static void fd_ref(grpc_fd *fd, const char *reason, const char *file, static void fd_ref(grpc_fd *fd, const char *reason, const char *file,
int line) { int line) {
ref_by(fd, 2, reason, file, line); ref_by(fd, 2, reason, file, line);
@ -833,9 +840,6 @@ static grpc_fd *fd_create(int fd, const char *name) {
char *fd_name; char *fd_name;
gpr_asprintf(&fd_name, "%s fd=%d", name, fd); gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
#ifdef GRPC_FD_REF_COUNT_DEBUG
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name);
#endif
gpr_free(fd_name); gpr_free(fd_name);
return new_fd; return new_fd;
} }

@ -134,9 +134,7 @@ static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *rec,
/* Return 1 if this fd is orphaned, 0 otherwise */ /* Return 1 if this fd is orphaned, 0 otherwise */
static bool fd_is_orphaned(grpc_fd *fd); static bool fd_is_orphaned(grpc_fd *fd);
/* Reference counting for fds */ #ifndef NDEBUG
//#define GRPC_FD_REF_COUNT_DEBUG
#ifdef GRPC_FD_REF_COUNT_DEBUG
static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line); static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line);
static void fd_unref(grpc_fd *fd, const char *reason, const char *file, static void fd_unref(grpc_fd *fd, const char *reason, const char *file,
int line); int line);
@ -263,14 +261,17 @@ cv_fd_table g_cvfds;
* fd_posix.c * fd_posix.c
*/ */
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) #define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__)
#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) #define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__)
static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) { int line) {
gpr_log(GPR_DEBUG, "FD %d %p ref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
(int)gpr_atm_no_barrier_load(&fd->refst), gpr_log(GPR_DEBUG,
(int)gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); "FD %d %p ref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
}
#else #else
#define REF_BY(fd, n, reason) ref_by(fd, n) #define REF_BY(fd, n, reason) ref_by(fd, n)
#define UNREF_BY(fd, n, reason) unref_by(fd, n) #define UNREF_BY(fd, n, reason) unref_by(fd, n)
@ -279,18 +280,19 @@ static void ref_by(grpc_fd *fd, int n) {
GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0);
} }
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) { int line) {
gpr_atm old; if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, gpr_log(GPR_DEBUG,
(int)gpr_atm_no_barrier_load(&fd->refst), "FD %d %p unref %d %" PRIdPTR " -> %" PRIdPTR " [%s; %s:%d]",
(int)gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); fd->fd, fd, n, gpr_atm_no_barrier_load(&fd->refst),
gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
}
#else #else
static void unref_by(grpc_fd *fd, int n) { static void unref_by(grpc_fd *fd, int n) {
gpr_atm old;
#endif #endif
old = gpr_atm_full_fetch_add(&fd->refst, -n); gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n);
if (old == n) { if (old == n) {
gpr_mu_destroy(&fd->mu); gpr_mu_destroy(&fd->mu);
grpc_iomgr_unregister_object(&fd->iomgr_object); grpc_iomgr_unregister_object(&fd->iomgr_object);
@ -321,9 +323,6 @@ static grpc_fd *fd_create(int fd, const char *name) {
gpr_asprintf(&name2, "%s fd=%d", name, fd); gpr_asprintf(&name2, "%s fd=%d", name, fd);
grpc_iomgr_register_object(&r->iomgr_object, name2); grpc_iomgr_register_object(&r->iomgr_object, name2);
gpr_free(name2); gpr_free(name2);
#ifdef GRPC_FD_REF_COUNT_DEBUG
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, r, name);
#endif
return r; return r;
} }
@ -417,7 +416,7 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
} }
/* increment refcount by two to avoid changing the orphan bit */ /* increment refcount by two to avoid changing the orphan bit */
#ifdef GRPC_FD_REF_COUNT_DEBUG #ifndef NDEBUG
static void fd_ref(grpc_fd *fd, const char *reason, const char *file, static void fd_ref(grpc_fd *fd, const char *reason, const char *file,
int line) { int line) {
ref_by(fd, 2, reason, file, line); ref_by(fd, 2, reason, file, line);

@ -41,6 +41,10 @@
grpc_tracer_flag grpc_polling_trace = grpc_tracer_flag grpc_polling_trace =
GRPC_TRACER_INITIALIZER(false); /* Disabled by default */ GRPC_TRACER_INITIALIZER(false); /* Disabled by default */
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_fd_refcount = GRPC_TRACER_INITIALIZER(false);
#endif
/** Default poll() function - a pointer so that it can be overridden by some /** Default poll() function - a pointer so that it can be overridden by some
* tests */ * tests */
grpc_poll_function_type grpc_poll_function = poll; grpc_poll_function_type grpc_poll_function = poll;

@ -62,7 +62,7 @@ bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
grpc_closure *next = c->next_data.next; grpc_closure *next = c->next_data.next;
grpc_error *error = c->error_data.error; grpc_error *error = c->error_data.error;
did_something = true; did_something = true;
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
c->scheduled = false; c->scheduled = false;
#endif #endif
c->cb(exec_ctx, c->cb_arg, error); c->cb(exec_ctx, c->cb_arg, error);
@ -85,10 +85,21 @@ void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
static void exec_ctx_run(grpc_exec_ctx *exec_ctx, grpc_closure *closure, static void exec_ctx_run(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_error *error) { grpc_error *error) {
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
closure->scheduled = false; closure->scheduled = false;
if (GRPC_TRACER_ON(grpc_trace_closure)) {
gpr_log(GPR_DEBUG, "running closure %p: created [%s:%d]: %s [%s:%d]",
closure, closure->file_created, closure->line_created,
closure->run ? "run" : "scheduled", closure->file_initiated,
closure->line_initiated);
}
#endif #endif
closure->cb(exec_ctx, closure->cb_arg, error); closure->cb(exec_ctx, closure->cb_arg, error);
#ifndef NDEBUG
if (GRPC_TRACER_ON(grpc_trace_closure)) {
gpr_log(GPR_DEBUG, "closure %p finished", closure);
}
#endif
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }

@ -58,7 +58,7 @@ static size_t run_closures(grpc_exec_ctx *exec_ctx, grpc_closure_list list) {
while (c != NULL) { while (c != NULL) {
grpc_closure *next = c->next_data.next; grpc_closure *next = c->next_data.next;
grpc_error *error = c->error_data.error; grpc_error *error = c->error_data.error;
#ifdef GRPC_CLOSURE_RICH_DEBUG #ifndef NDEBUG
c->scheduled = false; c->scheduled = false;
#endif #endif
c->cb(exec_ctx, c->cb_arg, error); c->cb(exec_ctx, c->cb_arg, error);

@ -25,6 +25,10 @@
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_fd_refcount;
#endif
/* A grpc_pollset is a set of file descriptors that a higher level item is /* A grpc_pollset is a set of file descriptors that a higher level item is
interested in. For example: interested in. For example:
- a server will typically keep a pollset containing all connected channels, - a server will typically keep a pollset containing all connected channels,

@ -31,6 +31,12 @@
#include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/pollset_uv.h" #include "src/core/lib/iomgr/pollset_uv.h"
#include "src/core/lib/debug/trace.h"
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_fd_refcount = GRPC_TRACER_INITIALIZER(false);
#endif
struct grpc_pollset { struct grpc_pollset {
uv_timer_t timer; uv_timer_t timer;
int shutting_down; int shutting_down;

@ -30,6 +30,10 @@
#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) #define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1)
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_fd_refcount = GRPC_TRACER_INITIALIZER(false);
#endif
gpr_mu grpc_polling_mu; gpr_mu grpc_polling_mu;
static grpc_pollset_worker *g_active_poller; static grpc_pollset_worker *g_active_poller;
static grpc_pollset_worker g_global_root_worker; static grpc_pollset_worker g_global_root_worker;

@ -163,15 +163,18 @@ static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
gpr_free(tcp); gpr_free(tcp);
} }
/*#define GRPC_TCP_REFCOUNT_DEBUG*/ #ifndef NDEBUG
#ifdef GRPC_TCP_REFCOUNT_DEBUG
#define TCP_UNREF(cl, tcp, reason) \ #define TCP_UNREF(cl, tcp, reason) \
tcp_unref((cl), (tcp), (reason), __FILE__, __LINE__) tcp_unref((cl), (tcp), (reason), __FILE__, __LINE__)
#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) #define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
const char *reason, const char *file, int line) { const char *reason, const char *file, int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, if (GRPC_TRACER_ON(grpc_tcp_trace)) {
reason, tcp->refcount.count, tcp->refcount.count - 1); gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"TCP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
val - 1);
}
if (gpr_unref(&tcp->refcount)) { if (gpr_unref(&tcp->refcount)) {
tcp_free(exec_ctx, tcp); tcp_free(exec_ctx, tcp);
} }
@ -179,8 +182,12 @@ static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
int line) { int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, if (GRPC_TRACER_ON(grpc_tcp_trace)) {
reason, tcp->refcount.count, tcp->refcount.count + 1); gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"TCP ref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
val + 1);
}
gpr_ref(&tcp->refcount); gpr_ref(&tcp->refcount);
} }
#else #else

@ -69,16 +69,18 @@ static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
gpr_free(tcp); gpr_free(tcp);
} }
/*#define GRPC_TCP_REFCOUNT_DEBUG*/ #ifndef NDEBUG
#ifdef GRPC_TCP_REFCOUNT_DEBUG
#define TCP_UNREF(exec_ctx, tcp, reason) \ #define TCP_UNREF(exec_ctx, tcp, reason) \
tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__) tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__)
#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) #define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
const char *reason, const char *file, int line) { const char *reason, const char *file, int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, if (GRPC_TRACER_ON(grpc_tcp_trace)) {
"TCP unref %p : %s %" PRIiPTR " -> %" PRIiPTR, tcp, reason, gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
tcp->refcount.count, tcp->refcount.count - 1); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"TCP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
val - 1);
}
if (gpr_unref(&tcp->refcount)) { if (gpr_unref(&tcp->refcount)) {
tcp_free(exec_ctx, tcp); tcp_free(exec_ctx, tcp);
} }
@ -86,9 +88,12 @@ static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
int line) { int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, if (GRPC_TRACER_ON(grpc_tcp_trace)) {
"TCP ref %p : %s %" PRIiPTR " -> %" PRIiPTR, tcp, reason, gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
tcp->refcount.count, tcp->refcount.count + 1); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"TCP ref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
val + 1);
}
gpr_ref(&tcp->refcount); gpr_ref(&tcp->refcount);
} }
#else #else

@ -48,6 +48,8 @@
#define GRPC_FIONBIO FIONBIO #define GRPC_FIONBIO FIONBIO
#endif #endif
grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false);
static grpc_error *set_non_block(SOCKET sock) { static grpc_error *set_non_block(SOCKET sock) {
int status; int status;
uint32_t param = 1; uint32_t param = 1;
@ -115,15 +117,18 @@ static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
gpr_free(tcp); gpr_free(tcp);
} }
/*#define GRPC_TCP_REFCOUNT_DEBUG*/ #ifndef NDEBUG
#ifdef GRPC_TCP_REFCOUNT_DEBUG
#define TCP_UNREF(exec_ctx, tcp, reason) \ #define TCP_UNREF(exec_ctx, tcp, reason) \
tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__) tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__)
#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) #define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
const char *reason, const char *file, int line) { const char *reason, const char *file, int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, if (GRPC_TRACER_ON(grpc_tcp_trace)) {
reason, tcp->refcount.count, tcp->refcount.count - 1); gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"TCP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
val - 1);
}
if (gpr_unref(&tcp->refcount)) { if (gpr_unref(&tcp->refcount)) {
tcp_free(exec_ctx, tcp); tcp_free(exec_ctx, tcp);
} }
@ -131,8 +136,12 @@ static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
int line) { int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, if (GRPC_TRACER_ON(grpc_tcp_trace)) {
reason, tcp->refcount.count, tcp->refcount.count + 1); gpr_atm val = gpr_atm_no_barrier_load(&tcp->refcount.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"TCP ref %p : %s %" PRIdPTR " -> %" PRIdPTR, tcp, reason, val,
val + 1);
}
gpr_ref(&tcp->refcount); gpr_ref(&tcp->refcount);
} }
#else #else

@ -29,6 +29,11 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_auth_context_refcount =
GRPC_TRACER_INITIALIZER(false);
#endif
/* --- grpc_call --- */ /* --- grpc_call --- */
grpc_call_error grpc_call_set_credentials(grpc_call *call, grpc_call_error grpc_call_set_credentials(grpc_call *call,
@ -122,14 +127,17 @@ grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained) {
return ctx; return ctx;
} }
#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG #ifndef NDEBUG
grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx, grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx,
const char *file, int line, const char *file, int line,
const char *reason) { const char *reason) {
if (ctx == NULL) return NULL; if (ctx == NULL) return NULL;
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, if (GRPC_TRACER_ON(grpc_trace_auth_context_refcount)) {
"AUTH_CONTEXT:%p ref %d -> %d %s", ctx, (int)ctx->refcount.count, gpr_atm val = gpr_atm_no_barrier_load(&ctx->refcount.count);
(int)ctx->refcount.count + 1, reason); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"AUTH_CONTEXT:%p ref %" PRIdPTR " -> %" PRIdPTR " %s", ctx, val,
val + 1, reason);
}
#else #else
grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) { grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) {
if (ctx == NULL) return NULL; if (ctx == NULL) return NULL;
@ -138,13 +146,16 @@ grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) {
return ctx; return ctx;
} }
#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_auth_context_unref(grpc_auth_context *ctx, const char *file, int line, void grpc_auth_context_unref(grpc_auth_context *ctx, const char *file, int line,
const char *reason) { const char *reason) {
if (ctx == NULL) return; if (ctx == NULL) return;
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, if (GRPC_TRACER_ON(grpc_trace_auth_context_refcount)) {
"AUTH_CONTEXT:%p unref %d -> %d %s", ctx, (int)ctx->refcount.count, gpr_atm val = gpr_atm_no_barrier_load(&ctx->refcount.count);
(int)ctx->refcount.count - 1, reason); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"AUTH_CONTEXT:%p unref %" PRIdPTR " -> %" PRIdPTR " %s", ctx, val,
val - 1, reason);
}
#else #else
void grpc_auth_context_unref(grpc_auth_context *ctx) { void grpc_auth_context_unref(grpc_auth_context *ctx) {
if (ctx == NULL) return; if (ctx == NULL) return;

@ -22,6 +22,10 @@
#include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/credentials.h"
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_auth_context_refcount;
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -50,7 +54,7 @@ struct grpc_auth_context {
grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained); grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained);
/* Refcounting. */ /* Refcounting. */
#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG #ifndef NDEBUG
#define GRPC_AUTH_CONTEXT_REF(p, r) \ #define GRPC_AUTH_CONTEXT_REF(p, r) \
grpc_auth_context_ref((p), __FILE__, __LINE__, (r)) grpc_auth_context_ref((p), __FILE__, __LINE__, (r))
#define GRPC_AUTH_CONTEXT_UNREF(p, r) \ #define GRPC_AUTH_CONTEXT_UNREF(p, r) \

@ -75,18 +75,20 @@ static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) {
gpr_free(ep); gpr_free(ep);
} }
/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/ #ifndef NDEBUG
#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG
#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \ #define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \
secure_endpoint_unref((exec_ctx), (ep), (reason), __FILE__, __LINE__) secure_endpoint_unref((exec_ctx), (ep), (reason), __FILE__, __LINE__)
#define SECURE_ENDPOINT_REF(ep, reason) \ #define SECURE_ENDPOINT_REF(ep, reason) \
secure_endpoint_ref((ep), (reason), __FILE__, __LINE__) secure_endpoint_ref((ep), (reason), __FILE__, __LINE__)
static void secure_endpoint_unref(secure_endpoint *ep, static void secure_endpoint_unref(grpc_exec_ctx *exec_ctx, secure_endpoint *ep,
grpc_closure_list *closure_list,
const char *reason, const char *file, const char *reason, const char *file,
int line) { int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d", if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) {
ep, reason, ep->ref.count, ep->ref.count - 1); gpr_atm val = gpr_atm_no_barrier_load(&ep->ref.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"SECENDP unref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep, reason, val,
val - 1);
}
if (gpr_unref(&ep->ref)) { if (gpr_unref(&ep->ref)) {
destroy(exec_ctx, ep); destroy(exec_ctx, ep);
} }
@ -94,8 +96,12 @@ static void secure_endpoint_unref(secure_endpoint *ep,
static void secure_endpoint_ref(secure_endpoint *ep, const char *reason, static void secure_endpoint_ref(secure_endpoint *ep, const char *reason,
const char *file, int line) { const char *file, int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d", if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) {
ep, reason, ep->ref.count, ep->ref.count + 1); gpr_atm val = gpr_atm_no_barrier_load(&ep->ref.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"SECENDP ref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep, reason, val,
val + 1);
}
gpr_ref(&ep->ref); gpr_ref(&ep->ref);
} }
#else #else

@ -43,6 +43,11 @@
#include "src/core/tsi/ssl_transport_security.h" #include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security_adapter.h" #include "src/core/tsi/transport_security_adapter.h"
#ifndef NDEBUG
grpc_tracer_flag grpc_trace_security_connector_refcount =
GRPC_TRACER_INITIALIZER(false);
#endif
/* -- Constants. -- */ /* -- Constants. -- */
#ifndef INSTALL_PREFIX #ifndef INSTALL_PREFIX
@ -142,14 +147,17 @@ void grpc_channel_security_connector_check_call_host(
} }
} }
#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG #ifndef NDEBUG
grpc_security_connector *grpc_security_connector_ref( grpc_security_connector *grpc_security_connector_ref(
grpc_security_connector *sc, const char *file, int line, grpc_security_connector *sc, const char *file, int line,
const char *reason) { const char *reason) {
if (sc == NULL) return NULL; if (sc == NULL) return NULL;
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, if (GRPC_TRACER_ON(grpc_trace_security_connector_refcount)) {
"SECURITY_CONNECTOR:%p ref %d -> %d %s", sc, gpr_atm val = gpr_atm_no_barrier_load(&sc->refcount.count);
(int)sc->refcount.count, (int)sc->refcount.count + 1, reason); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"SECURITY_CONNECTOR:%p ref %" PRIdPTR " -> %" PRIdPTR " %s", sc,
val, val + 1, reason);
}
#else #else
grpc_security_connector *grpc_security_connector_ref( grpc_security_connector *grpc_security_connector_ref(
grpc_security_connector *sc) { grpc_security_connector *sc) {
@ -159,15 +167,18 @@ grpc_security_connector *grpc_security_connector_ref(
return sc; return sc;
} }
#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx, void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc, grpc_security_connector *sc,
const char *file, int line, const char *file, int line,
const char *reason) { const char *reason) {
if (sc == NULL) return; if (sc == NULL) return;
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, if (GRPC_TRACER_ON(grpc_trace_security_connector_refcount)) {
"SECURITY_CONNECTOR:%p unref %d -> %d %s", sc, gpr_atm val = gpr_atm_no_barrier_load(&sc->refcount.count);
(int)sc->refcount.count, (int)sc->refcount.count - 1, reason); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"SECURITY_CONNECTOR:%p unref %" PRIdPTR " -> %" PRIdPTR " %s", sc,
val, val - 1, reason);
}
#else #else
void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx, void grpc_security_connector_unref(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc) { grpc_security_connector *sc) {

@ -29,6 +29,10 @@
#include "src/core/tsi/ssl_transport_security.h" #include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security_interface.h" #include "src/core/tsi/transport_security_interface.h"
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_security_connector_refcount;
#endif
/* --- status enum. --- */ /* --- status enum. --- */
typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status; typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status;
@ -66,7 +70,7 @@ struct grpc_security_connector {
}; };
/* Refcounting. */ /* Refcounting. */
#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG #ifndef NDEBUG
#define GRPC_SECURITY_CONNECTOR_REF(p, r) \ #define GRPC_SECURITY_CONNECTOR_REF(p, r) \
grpc_security_connector_ref((p), __FILE__, __LINE__, (r)) grpc_security_connector_ref((p), __FILE__, __LINE__, (r))
#define GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, p, r) \ #define GRPC_SECURITY_CONNECTOR_UNREF(exec_ctx, p, r) \

@ -1,137 +0,0 @@
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "src/core/lib/support/stack_lockfree.h"
#include <stdlib.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
/* The lockfree node structure is a single architecture-level
word that allows for an atomic CAS to set it up. */
struct lockfree_node_contents {
/* next thing to look at. Actual index for head, next index otherwise */
uint16_t index;
#ifdef GPR_ARCH_64
uint16_t pad;
uint32_t aba_ctr;
#else
#ifdef GPR_ARCH_32
uint16_t aba_ctr;
#else
#error Unsupported bit width architecture
#endif
#endif
};
/* Use a union to make sure that these are in the same bits as an atm word */
typedef union lockfree_node {
gpr_atm atm;
struct lockfree_node_contents contents;
} lockfree_node;
/* make sure that entries aligned to 8-bytes */
#define ENTRY_ALIGNMENT_BITS 3
/* reserve this entry as invalid */
#define INVALID_ENTRY_INDEX ((1 << 16) - 1)
struct gpr_stack_lockfree {
lockfree_node *entries;
lockfree_node head; /* An atomic entry describing curr head */
};
gpr_stack_lockfree *gpr_stack_lockfree_create(size_t entries) {
gpr_stack_lockfree *stack;
stack = (gpr_stack_lockfree *)gpr_malloc(sizeof(*stack));
/* Since we only allocate 16 bits to represent an entry number,
* make sure that we are within the desired range */
/* Reserve the highest entry number as a dummy */
GPR_ASSERT(entries < INVALID_ENTRY_INDEX);
stack->entries = (lockfree_node *)gpr_malloc_aligned(
entries * sizeof(stack->entries[0]), ENTRY_ALIGNMENT_BITS);
/* Clear out all entries */
memset(stack->entries, 0, entries * sizeof(stack->entries[0]));
memset(&stack->head, 0, sizeof(stack->head));
GPR_ASSERT(sizeof(stack->entries->atm) == sizeof(stack->entries->contents));
/* Point the head at reserved dummy entry */
stack->head.contents.index = INVALID_ENTRY_INDEX;
/* Fill in the pad and aba_ctr to avoid confusing memcheck tools */
#ifdef GPR_ARCH_64
stack->head.contents.pad = 0;
#endif
stack->head.contents.aba_ctr = 0;
return stack;
}
void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack) {
gpr_free_aligned(stack->entries);
gpr_free(stack);
}
int gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
lockfree_node head;
lockfree_node newhead;
lockfree_node curent;
lockfree_node newent;
/* First fill in the entry's index and aba ctr for new head */
newhead.contents.index = (uint16_t)entry;
#ifdef GPR_ARCH_64
/* Fill in the pad to avoid confusing memcheck tools */
newhead.contents.pad = 0;
#endif
/* Also post-increment the aba_ctr */
curent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
newhead.contents.aba_ctr = ++curent.contents.aba_ctr;
gpr_atm_no_barrier_store(&stack->entries[entry].atm, curent.atm);
do {
/* Atomically get the existing head value for use */
head.atm = gpr_atm_no_barrier_load(&(stack->head.atm));
/* Point to it */
newent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
newent.contents.index = head.contents.index;
gpr_atm_no_barrier_store(&stack->entries[entry].atm, newent.atm);
} while (!gpr_atm_rel_cas(&(stack->head.atm), head.atm, newhead.atm));
/* Use rel_cas above to make sure that entry index is set properly */
return head.contents.index == INVALID_ENTRY_INDEX;
}
int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack) {
lockfree_node head;
lockfree_node newhead;
do {
head.atm = gpr_atm_acq_load(&(stack->head.atm));
if (head.contents.index == INVALID_ENTRY_INDEX) {
return -1;
}
newhead.atm =
gpr_atm_no_barrier_load(&(stack->entries[head.contents.index].atm));
} while (!gpr_atm_no_barrier_cas(&(stack->head.atm), head.atm, newhead.atm));
return head.contents.index;
}

@ -1,38 +0,0 @@
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H
#define GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H
#include <stddef.h>
typedef struct gpr_stack_lockfree gpr_stack_lockfree;
/* This stack must specify the maximum number of entries to track.
The current implementation only allows up to 65534 entries */
gpr_stack_lockfree *gpr_stack_lockfree_create(size_t entries);
void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack);
/* Pass in a valid entry number for the next stack entry */
/* Returns 1 if this is the first element on the stack, 0 otherwise */
int gpr_stack_lockfree_push(gpr_stack_lockfree *, int entry);
/* Returns -1 on empty or the actual entry number */
int gpr_stack_lockfree_pop(gpr_stack_lockfree *stack);
#endif /* GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H */

@ -22,26 +22,26 @@
#ifdef GRPC_TIMERS_RDTSC #ifdef GRPC_TIMERS_RDTSC
#if defined(__i386__) #if defined(__i386__)
static void gpr_get_cycle_counter(long long int *clk) { static void gpr_get_cycle_counter(int64_t int *clk) {
long long int ret; int64_t int ret;
__asm__ volatile("rdtsc" : "=A"(ret)); __asm__ volatile("rdtsc" : "=A"(ret));
*clk = ret; *clk = ret;
} }
// ---------------------------------------------------------------- // ----------------------------------------------------------------
#elif defined(__x86_64__) || defined(__amd64__) #elif defined(__x86_64__) || defined(__amd64__)
static void gpr_get_cycle_counter(long long int *clk) { static void gpr_get_cycle_counter(int64_t *clk) {
unsigned long long low, high; uint64_t low, high;
__asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
*clk = (long long)(high << 32) | (long long)low; *clk = (int64_t)(high << 32) | (int64_t)low;
} }
#endif #endif
static double cycles_per_second = 0; static double cycles_per_second = 0;
static long long int start_cycle; static int64_t start_cycle;
void gpr_precise_clock_init(void) { void gpr_precise_clock_init(void) {
time_t start; time_t start;
long long end_cycle; int64_t end_cycle;
gpr_log(GPR_DEBUG, "Calibrating timers"); gpr_log(GPR_DEBUG, "Calibrating timers");
start = time(NULL); start = time(NULL);
while (time(NULL) == start) while (time(NULL) == start)
@ -55,7 +55,7 @@ void gpr_precise_clock_init(void) {
} }
void gpr_precise_clock_now(gpr_timespec *clk) { void gpr_precise_clock_now(gpr_timespec *clk) {
long long int counter; int64_t counter;
double secs; double secs;
gpr_get_cycle_counter(&counter); gpr_get_cycle_counter(&counter);
secs = (double)(counter - start_cycle) / cycles_per_second; secs = (double)(counter - start_cycle) / cycles_per_second;

@ -457,7 +457,7 @@ void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call,
exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent); exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent);
} }
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
#define REF_REASON reason #define REF_REASON reason
#define REF_ARG , const char *reason #define REF_ARG , const char *reason
#else #else
@ -929,33 +929,6 @@ static grpc_compression_algorithm decode_compression(grpc_mdelem md) {
return algorithm; return algorithm;
} }
static void recv_common_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_metadata_batch *b) {
if (b->idx.named.grpc_status != NULL) {
uint32_t status_code = decode_status(b->idx.named.grpc_status->md);
grpc_error *error =
status_code == GRPC_STATUS_OK
? GRPC_ERROR_NONE
: grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Error received from peer"),
GRPC_ERROR_INT_GRPC_STATUS,
(intptr_t)status_code);
if (b->idx.named.grpc_message != NULL) {
error = grpc_error_set_str(
error, GRPC_ERROR_STR_GRPC_MESSAGE,
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_message->md)));
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_message);
} else if (error != GRPC_ERROR_NONE) {
error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
grpc_empty_slice());
}
set_status_from_error(exec_ctx, call, STATUS_FROM_WIRE, error);
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_status);
}
}
static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b, static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
int is_trailing) { int is_trailing) {
if (b->list.count == 0) return; if (b->list.count == 0) return;
@ -980,8 +953,6 @@ static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call, static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_metadata_batch *b) { grpc_metadata_batch *b) {
recv_common_filter(exec_ctx, call, b);
if (b->idx.named.grpc_encoding != NULL) { if (b->idx.named.grpc_encoding != NULL) {
GPR_TIMER_BEGIN("incoming_compression_algorithm", 0); GPR_TIMER_BEGIN("incoming_compression_algorithm", 0);
set_incoming_compression_algorithm( set_incoming_compression_algorithm(
@ -989,7 +960,6 @@ static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
GPR_TIMER_END("incoming_compression_algorithm", 0); GPR_TIMER_END("incoming_compression_algorithm", 0);
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_encoding); grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_encoding);
} }
if (b->idx.named.grpc_accept_encoding != NULL) { if (b->idx.named.grpc_accept_encoding != NULL) {
GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0); GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
set_encodings_accepted_by_peer(exec_ctx, call, set_encodings_accepted_by_peer(exec_ctx, call,
@ -997,14 +967,33 @@ static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_accept_encoding); grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_accept_encoding);
GPR_TIMER_END("encodings_accepted_by_peer", 0); GPR_TIMER_END("encodings_accepted_by_peer", 0);
} }
publish_app_metadata(call, b, false); publish_app_metadata(call, b, false);
} }
static void recv_trailing_filter(grpc_exec_ctx *exec_ctx, void *args, static void recv_trailing_filter(grpc_exec_ctx *exec_ctx, void *args,
grpc_metadata_batch *b) { grpc_metadata_batch *b) {
grpc_call *call = args; grpc_call *call = args;
recv_common_filter(exec_ctx, call, b); if (b->idx.named.grpc_status != NULL) {
uint32_t status_code = decode_status(b->idx.named.grpc_status->md);
grpc_error *error =
status_code == GRPC_STATUS_OK
? GRPC_ERROR_NONE
: grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Error received from peer"),
GRPC_ERROR_INT_GRPC_STATUS,
(intptr_t)status_code);
if (b->idx.named.grpc_message != NULL) {
error = grpc_error_set_str(
error, GRPC_ERROR_STR_GRPC_MESSAGE,
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_message->md)));
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_message);
} else if (error != GRPC_ERROR_NONE) {
error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
grpc_empty_slice());
}
set_status_from_error(exec_ctx, call, STATUS_FROM_WIRE, error);
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_status);
}
publish_app_metadata(call, b, true); publish_app_metadata(call, b, true);
} }

@ -62,7 +62,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call, void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_completion_queue *cq); grpc_completion_queue *cq);
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_call_internal_ref(grpc_call *call, const char *reason); void grpc_call_internal_ref(grpc_call *call, const char *reason);
void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *call, void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *call,
const char *reason); const char *reason);

@ -345,7 +345,7 @@ grpc_call *grpc_channel_create_registered_call(
return call; return call;
} }
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
#define REF_REASON reason #define REF_REASON reason
#define REF_ARG , const char *reason #define REF_ARG , const char *reason
#else #else

@ -59,7 +59,7 @@ grpc_mdelem grpc_channel_get_reffed_status_elem(grpc_exec_ctx *exec_ctx,
size_t grpc_channel_get_call_size_estimate(grpc_channel *channel); size_t grpc_channel_get_call_size_estimate(grpc_channel *channel);
void grpc_channel_update_call_size_estimate(grpc_channel *channel, size_t size); void grpc_channel_update_call_size_estimate(grpc_channel *channel, size_t size);
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_channel_internal_ref(grpc_channel *channel, const char *reason); void grpc_channel_internal_ref(grpc_channel *channel, const char *reason);
void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel, void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
const char *reason); const char *reason);

@ -38,6 +38,7 @@
grpc_tracer_flag grpc_trace_operation_failures = GRPC_TRACER_INITIALIZER(false); grpc_tracer_flag grpc_trace_operation_failures = GRPC_TRACER_INITIALIZER(false);
#ifndef NDEBUG #ifndef NDEBUG
grpc_tracer_flag grpc_trace_pending_tags = GRPC_TRACER_INITIALIZER(false); grpc_tracer_flag grpc_trace_pending_tags = GRPC_TRACER_INITIALIZER(false);
grpc_tracer_flag grpc_trace_cq_refcount = GRPC_TRACER_INITIALIZER(false);
#endif #endif
typedef struct { typedef struct {
@ -472,11 +473,15 @@ int grpc_get_cq_poll_num(grpc_completion_queue *cq) {
return cur_num_polls; return cur_num_polls;
} }
#ifdef GRPC_CQ_REF_COUNT_DEBUG #ifndef NDEBUG
void grpc_cq_internal_ref(grpc_completion_queue *cq, const char *reason, void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
const char *file, int line) { const char *file, int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p ref %d -> %d %s", cq, if (GRPC_TRACER_ON(grpc_trace_cq_refcount)) {
(int)cq->owning_refs.count, (int)cq->owning_refs.count + 1, reason); gpr_atm val = gpr_atm_no_barrier_load(&cq->owning_refs.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"CQ:%p ref %" PRIdPTR " -> %" PRIdPTR " %s", cq, val, val + 1,
reason);
}
#else #else
void grpc_cq_internal_ref(grpc_completion_queue *cq) { void grpc_cq_internal_ref(grpc_completion_queue *cq) {
#endif #endif
@ -489,12 +494,15 @@ static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_CQ_INTERNAL_UNREF(exec_ctx, cq, "pollset_destroy"); GRPC_CQ_INTERNAL_UNREF(exec_ctx, cq, "pollset_destroy");
} }
#ifdef GRPC_CQ_REF_COUNT_DEBUG #ifndef NDEBUG
void grpc_cq_internal_unref(grpc_completion_queue *cq, const char *reason, void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cq,
const char *file, int line) { const char *reason, const char *file, int line) {
cq_data *cqd = &cq->data; if (GRPC_TRACER_ON(grpc_trace_cq_refcount)) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", cq, gpr_atm val = gpr_atm_no_barrier_load(&cq->owning_refs.count);
(int)cqd->owning_refs.count, (int)cqd->owning_refs.count - 1, reason); gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"CQ:%p unref %" PRIdPTR " -> %" PRIdPTR " %s", cq, val, val - 1,
reason);
}
#else #else
void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx, void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx,
grpc_completion_queue *cq) { grpc_completion_queue *cq) {
@ -563,7 +571,8 @@ static void cq_check_tag(grpc_completion_queue *cq, void *tag, bool lock_cq) {
static void cq_check_tag(grpc_completion_queue *cq, void *tag, bool lock_cq) {} static void cq_check_tag(grpc_completion_queue *cq, void *tag, bool lock_cq) {}
#endif #endif
/* Queue a GRPC_OP_COMPLETED operation to a completion queue (with a completion /* Queue a GRPC_OP_COMPLETED operation to a completion queue (with a
* completion
* type of GRPC_CQ_NEXT) */ * type of GRPC_CQ_NEXT) */
static void cq_end_op_for_next(grpc_exec_ctx *exec_ctx, static void cq_end_op_for_next(grpc_exec_ctx *exec_ctx,
grpc_completion_queue *cq, void *tag, grpc_completion_queue *cq, void *tag,
@ -639,7 +648,8 @@ static void cq_end_op_for_next(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
} }
/* Queue a GRPC_OP_COMPLETED operation to a completion queue (with a completion /* Queue a GRPC_OP_COMPLETED operation to a completion queue (with a
* completion
* type of GRPC_CQ_PLUCK) */ * type of GRPC_CQ_PLUCK) */
static void cq_end_op_for_pluck(grpc_exec_ctx *exec_ctx, static void cq_end_op_for_pluck(grpc_exec_ctx *exec_ctx,
grpc_completion_queue *cq, void *tag, grpc_completion_queue *cq, void *tag,
@ -743,7 +753,8 @@ static bool cq_is_next_finished(grpc_exec_ctx *exec_ctx, void *arg) {
gpr_atm_no_barrier_load(&cqd->things_queued_ever); gpr_atm_no_barrier_load(&cqd->things_queued_ever);
/* Pop a cq_completion from the queue. Returns NULL if the queue is empty /* Pop a cq_completion from the queue. Returns NULL if the queue is empty
* might return NULL in some cases even if the queue is not empty; but that * might return NULL in some cases even if the queue is not empty; but
* that
* is ok and doesn't affect correctness. Might effect the tail latencies a * is ok and doesn't affect correctness. Might effect the tail latencies a
* bit) */ * bit) */
a->stolen_completion = cq_event_queue_pop(&cqd->queue); a->stolen_completion = cq_event_queue_pop(&cqd->queue);
@ -838,7 +849,8 @@ static grpc_event cq_next(grpc_completion_queue *cq, gpr_timespec deadline,
/* If c == NULL it means either the queue is empty OR in an transient /* If c == NULL it means either the queue is empty OR in an transient
inconsistent state. If it is the latter, we shold do a 0-timeout poll inconsistent state. If it is the latter, we shold do a 0-timeout poll
so that the thread comes back quickly from poll to make a second so that the thread comes back quickly from poll to make a second
attempt at popping. Not doing this can potentially deadlock this thread attempt at popping. Not doing this can potentially deadlock this
thread
forever (if the deadline is infinity) */ forever (if the deadline is infinity) */
if (cq_event_queue_num_items(&cqd->queue) > 0) { if (cq_event_queue_num_items(&cqd->queue) > 0) {
iteration_deadline = gpr_time_0(GPR_CLOCK_MONOTONIC); iteration_deadline = gpr_time_0(GPR_CLOCK_MONOTONIC);
@ -851,8 +863,10 @@ static grpc_event cq_next(grpc_completion_queue *cq, gpr_timespec deadline,
empty. If so, keep retrying but do not return GRPC_QUEUE_SHUTDOWN */ empty. If so, keep retrying but do not return GRPC_QUEUE_SHUTDOWN */
if (cq_event_queue_num_items(&cqd->queue) > 0) { if (cq_event_queue_num_items(&cqd->queue) > 0) {
/* Go to the beginning of the loop. No point doing a poll because /* Go to the beginning of the loop. No point doing a poll because
(cq->shutdown == true) is only possible when there is no pending work (cq->shutdown == true) is only possible when there is no pending
(i.e cq->pending_events == 0) and any outstanding grpc_cq_completion work
(i.e cq->pending_events == 0) and any outstanding
grpc_cq_completion
events are already queued on this cq */ events are already queued on this cq */
continue; continue;
} }

@ -30,8 +30,10 @@
extern grpc_tracer_flag grpc_cq_pluck_trace; extern grpc_tracer_flag grpc_cq_pluck_trace;
extern grpc_tracer_flag grpc_cq_event_timeout_trace; extern grpc_tracer_flag grpc_cq_event_timeout_trace;
extern grpc_tracer_flag grpc_trace_operation_failures; extern grpc_tracer_flag grpc_trace_operation_failures;
#ifndef NDEBUG #ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_pending_tags; extern grpc_tracer_flag grpc_trace_pending_tags;
extern grpc_tracer_flag grpc_trace_cq_refcount;
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -52,9 +54,7 @@ typedef struct grpc_cq_completion {
uintptr_t next; uintptr_t next;
} grpc_cq_completion; } grpc_cq_completion;
//#define GRPC_CQ_REF_COUNT_DEBUG #ifndef NDEBUG
#ifdef GRPC_CQ_REF_COUNT_DEBUG
void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason, void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
const char *file, int line); const char *file, int line);
void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc, void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,

@ -126,18 +126,23 @@ void grpc_init(void) {
grpc_register_tracer("channel_stack_builder", grpc_register_tracer("channel_stack_builder",
&grpc_trace_channel_stack_builder); &grpc_trace_channel_stack_builder);
grpc_register_tracer("http1", &grpc_http1_trace); grpc_register_tracer("http1", &grpc_http1_trace);
grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace); grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace); // default on
grpc_register_tracer("combiner", &grpc_combiner_trace); grpc_register_tracer("combiner", &grpc_combiner_trace);
grpc_register_tracer("server_channel", &grpc_server_channel_trace); grpc_register_tracer("server_channel", &grpc_server_channel_trace);
grpc_register_tracer("bdp_estimator", &grpc_bdp_estimator_trace); grpc_register_tracer("bdp_estimator", &grpc_bdp_estimator_trace);
// Default pluck trace to 1 grpc_register_tracer("queue_timeout",
grpc_register_tracer("queue_timeout", &grpc_cq_event_timeout_trace); &grpc_cq_event_timeout_trace); // default on
// Default timeout trace to 1
grpc_register_tracer("op_failure", &grpc_trace_operation_failures); grpc_register_tracer("op_failure", &grpc_trace_operation_failures);
grpc_register_tracer("resource_quota", &grpc_resource_quota_trace); grpc_register_tracer("resource_quota", &grpc_resource_quota_trace);
grpc_register_tracer("call_error", &grpc_call_error_trace); grpc_register_tracer("call_error", &grpc_call_error_trace);
#ifndef NDEBUG #ifndef NDEBUG
grpc_register_tracer("pending_tags", &grpc_trace_pending_tags); grpc_register_tracer("pending_tags", &grpc_trace_pending_tags);
grpc_register_tracer("queue_refcount", &grpc_trace_cq_refcount);
grpc_register_tracer("closure", &grpc_trace_closure);
grpc_register_tracer("error_refcount", &grpc_trace_error_refcount);
grpc_register_tracer("stream_refcount", &grpc_trace_stream_refcount);
grpc_register_tracer("fd_refcount", &grpc_trace_fd_refcount);
grpc_register_tracer("metadata", &grpc_trace_metadata);
#endif #endif
grpc_security_pre_init(); grpc_security_pre_init();
grpc_iomgr_init(&exec_ctx); grpc_iomgr_init(&exec_ctx);

@ -32,9 +32,19 @@
#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/channel_init.h"
#include "src/core/tsi/transport_security_interface.h" #include "src/core/tsi/transport_security_interface.h"
#ifndef NDEBUG
#include "src/core/lib/security/context/security_context.h"
#endif
void grpc_security_pre_init(void) { void grpc_security_pre_init(void) {
grpc_register_tracer("secure_endpoint", &grpc_trace_secure_endpoint); grpc_register_tracer("secure_endpoint", &grpc_trace_secure_endpoint);
grpc_register_tracer("transport_security", &tsi_tracing_enabled); grpc_register_tracer("transport_security", &tsi_tracing_enabled);
#ifndef NDEBUG
grpc_register_tracer("auth_context_refcount",
&grpc_trace_auth_context_refcount);
grpc_register_tracer("security_connector_refcount",
&grpc_trace_security_connector_refcount);
#endif
} }
static bool maybe_prepend_client_auth_filter( static bool maybe_prepend_client_auth_filter(

@ -475,6 +475,7 @@ static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
*rc->data.registered.deadline = calld->deadline; *rc->data.registered.deadline = calld->deadline;
if (rc->data.registered.optional_payload) { if (rc->data.registered.optional_payload) {
*rc->data.registered.optional_payload = calld->payload; *rc->data.registered.optional_payload = calld->payload;
calld->payload = NULL;
} }
break; break;
default: default:
@ -878,6 +879,7 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_slice_unref_internal(exec_ctx, calld->path); grpc_slice_unref_internal(exec_ctx, calld->path);
} }
grpc_metadata_array_destroy(&calld->initial_metadata); grpc_metadata_array_destroy(&calld->initial_metadata);
grpc_byte_buffer_destroy(calld->payload);
gpr_mu_destroy(&calld->mu_state); gpr_mu_destroy(&calld->mu_state);

@ -47,7 +47,8 @@
* used to determine which kind of element a pointer refers to. * used to determine which kind of element a pointer refers to.
*/ */
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifndef NDEBUG
grpc_tracer_flag grpc_trace_metadata = GRPC_TRACER_INITIALIZER(false);
#define DEBUG_ARGS , const char *file, int line #define DEBUG_ARGS , const char *file, int line
#define FWD_DEBUG_ARGS , file, line #define FWD_DEBUG_ARGS , file, line
#define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s), __FILE__, __LINE__) #define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s), __FILE__, __LINE__)
@ -144,15 +145,17 @@ static int is_mdelem_static(grpc_mdelem e) {
static void ref_md_locked(mdtab_shard *shard, static void ref_md_locked(mdtab_shard *shard,
interned_metadata *md DEBUG_ARGS) { interned_metadata *md DEBUG_ARGS) {
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifndef NDEBUG
char *key_str = grpc_slice_to_c_string(md->key); if (GRPC_TRACER_ON(grpc_trace_metadata)) {
char *value_str = grpc_slice_to_c_string(md->value); char *key_str = grpc_slice_to_c_string(md->key);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, char *value_str = grpc_slice_to_c_string(md->value);
"ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
gpr_atm_no_barrier_load(&md->refcnt), "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", (void *)md,
gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str); gpr_atm_no_barrier_load(&md->refcnt),
gpr_free(key_str); gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str);
gpr_free(value_str); gpr_free(key_str);
gpr_free(value_str);
}
#endif #endif
if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) { if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) {
gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -1); gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -1);
@ -243,13 +246,16 @@ grpc_mdelem grpc_mdelem_create(
allocated->key = grpc_slice_ref_internal(key); allocated->key = grpc_slice_ref_internal(key);
allocated->value = grpc_slice_ref_internal(value); allocated->value = grpc_slice_ref_internal(value);
gpr_atm_rel_store(&allocated->refcnt, 1); gpr_atm_rel_store(&allocated->refcnt, 1);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifndef NDEBUG
char *key_str = grpc_slice_to_c_string(allocated->key); if (GRPC_TRACER_ON(grpc_trace_metadata)) {
char *value_str = grpc_slice_to_c_string(allocated->value); char *key_str = grpc_slice_to_c_string(allocated->key);
gpr_log(GPR_DEBUG, "ELM ALLOC:%p:%zu: '%s' = '%s'", (void *)allocated, char *value_str = grpc_slice_to_c_string(allocated->value);
gpr_atm_no_barrier_load(&allocated->refcnt), key_str, value_str); gpr_log(GPR_DEBUG, "ELM ALLOC:%p:%" PRIdPTR ": '%s' = '%s'",
gpr_free(key_str); (void *)allocated, gpr_atm_no_barrier_load(&allocated->refcnt),
gpr_free(value_str); key_str, value_str);
gpr_free(key_str);
gpr_free(value_str);
}
#endif #endif
return GRPC_MAKE_MDELEM(allocated, GRPC_MDELEM_STORAGE_ALLOCATED); return GRPC_MAKE_MDELEM(allocated, GRPC_MDELEM_STORAGE_ALLOCATED);
} }
@ -294,13 +300,15 @@ grpc_mdelem grpc_mdelem_create(
md->bucket_next = shard->elems[idx]; md->bucket_next = shard->elems[idx];
shard->elems[idx] = md; shard->elems[idx] = md;
gpr_mu_init(&md->mu_user_data); gpr_mu_init(&md->mu_user_data);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifndef NDEBUG
char *key_str = grpc_slice_to_c_string(md->key); if (GRPC_TRACER_ON(grpc_trace_metadata)) {
char *value_str = grpc_slice_to_c_string(md->value); char *key_str = grpc_slice_to_c_string(md->key);
gpr_log(GPR_DEBUG, "ELM NEW:%p:%zu: '%s' = '%s'", (void *)md, char *value_str = grpc_slice_to_c_string(md->value);
gpr_atm_no_barrier_load(&md->refcnt), key_str, value_str); gpr_log(GPR_DEBUG, "ELM NEW:%p:%" PRIdPTR ": '%s' = '%s'", (void *)md,
gpr_free(key_str); gpr_atm_no_barrier_load(&md->refcnt), key_str, value_str);
gpr_free(value_str); gpr_free(key_str);
gpr_free(value_str);
}
#endif #endif
shard->count++; shard->count++;
@ -356,15 +364,17 @@ grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd DEBUG_ARGS) {
break; break;
case GRPC_MDELEM_STORAGE_INTERNED: { case GRPC_MDELEM_STORAGE_INTERNED: {
interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd); interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifndef NDEBUG
char *key_str = grpc_slice_to_c_string(md->key); if (GRPC_TRACER_ON(grpc_trace_metadata)) {
char *value_str = grpc_slice_to_c_string(md->value); char *key_str = grpc_slice_to_c_string(md->key);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, char *value_str = grpc_slice_to_c_string(md->value);
"ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
gpr_atm_no_barrier_load(&md->refcnt), "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'",
gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str); (void *)md, gpr_atm_no_barrier_load(&md->refcnt),
gpr_free(key_str); gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str);
gpr_free(value_str); gpr_free(key_str);
gpr_free(value_str);
}
#endif #endif
/* we can assume the ref count is >= 1 as the application is calling /* we can assume the ref count is >= 1 as the application is calling
this function - meaning that no adjustment to mdtab_free is necessary, this function - meaning that no adjustment to mdtab_free is necessary,
@ -376,15 +386,17 @@ grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd DEBUG_ARGS) {
} }
case GRPC_MDELEM_STORAGE_ALLOCATED: { case GRPC_MDELEM_STORAGE_ALLOCATED: {
allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd); allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifndef NDEBUG
char *key_str = grpc_slice_to_c_string(md->key); if (GRPC_TRACER_ON(grpc_trace_metadata)) {
char *value_str = grpc_slice_to_c_string(md->value); char *key_str = grpc_slice_to_c_string(md->key);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, char *value_str = grpc_slice_to_c_string(md->value);
"ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
gpr_atm_no_barrier_load(&md->refcnt), "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'",
gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str); (void *)md, gpr_atm_no_barrier_load(&md->refcnt),
gpr_free(key_str); gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str);
gpr_free(value_str); gpr_free(key_str);
gpr_free(value_str);
}
#endif #endif
/* we can assume the ref count is >= 1 as the application is calling /* we can assume the ref count is >= 1 as the application is calling
this function - meaning that no adjustment to mdtab_free is necessary, this function - meaning that no adjustment to mdtab_free is necessary,
@ -404,15 +416,17 @@ void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem gmd DEBUG_ARGS) {
break; break;
case GRPC_MDELEM_STORAGE_INTERNED: { case GRPC_MDELEM_STORAGE_INTERNED: {
interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd); interned_metadata *md = (interned_metadata *)GRPC_MDELEM_DATA(gmd);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifndef NDEBUG
char *key_str = grpc_slice_to_c_string(md->key); if (GRPC_TRACER_ON(grpc_trace_metadata)) {
char *value_str = grpc_slice_to_c_string(md->value); char *key_str = grpc_slice_to_c_string(md->key);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, char *value_str = grpc_slice_to_c_string(md->value);
"ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
gpr_atm_no_barrier_load(&md->refcnt), "ELM UNREF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'",
gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str); (void *)md, gpr_atm_no_barrier_load(&md->refcnt),
gpr_free(key_str); gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str);
gpr_free(value_str); gpr_free(key_str);
gpr_free(value_str);
}
#endif #endif
uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key), uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key),
grpc_slice_hash(md->value)); grpc_slice_hash(md->value));
@ -428,15 +442,17 @@ void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem gmd DEBUG_ARGS) {
} }
case GRPC_MDELEM_STORAGE_ALLOCATED: { case GRPC_MDELEM_STORAGE_ALLOCATED: {
allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd); allocated_metadata *md = (allocated_metadata *)GRPC_MDELEM_DATA(gmd);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifndef NDEBUG
char *key_str = grpc_slice_to_c_string(md->key); if (GRPC_TRACER_ON(grpc_trace_metadata)) {
char *value_str = grpc_slice_to_c_string(md->value); char *key_str = grpc_slice_to_c_string(md->key);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, char *value_str = grpc_slice_to_c_string(md->value);
"ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
gpr_atm_no_barrier_load(&md->refcnt), "ELM UNREF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'",
gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str); (void *)md, gpr_atm_no_barrier_load(&md->refcnt),
gpr_free(key_str); gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str);
gpr_free(value_str); gpr_free(key_str);
gpr_free(value_str);
}
#endif #endif
const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1); const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
GPR_ASSERT(prev_refcount >= 1); GPR_ASSERT(prev_refcount >= 1);

@ -25,6 +25,10 @@
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_metadata;
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -132,9 +136,7 @@ void *grpc_mdelem_get_user_data(grpc_mdelem md,
void *grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void *), void *grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void *),
void *user_data); void *user_data);
/* Reference counting */ #ifndef NDEBUG
//#define GRPC_METADATA_REFCOUNT_DEBUG
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__) #define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__)
#define GRPC_MDELEM_UNREF(exec_ctx, s) \ #define GRPC_MDELEM_UNREF(exec_ctx, s) \
grpc_mdelem_unref((exec_ctx), (s), __FILE__, __LINE__) grpc_mdelem_unref((exec_ctx), (s), __FILE__, __LINE__)

@ -31,25 +31,33 @@
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/transport_impl.h" #include "src/core/lib/transport/transport_impl.h"
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
grpc_tracer_flag grpc_trace_stream_refcount = GRPC_TRACER_INITIALIZER(false);
#endif
#ifndef NDEBUG
void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) { void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) {
gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count); if (GRPC_TRACER_ON(grpc_trace_stream_refcount)) {
gpr_log(GPR_DEBUG, "%s %p:%p REF %" PRIdPTR "->%" PRIdPTR " %s", gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count);
refcount->object_type, refcount, refcount->destroy.cb_arg, val, gpr_log(GPR_DEBUG, "%s %p:%p REF %" PRIdPTR "->%" PRIdPTR " %s",
val + 1, reason); refcount->object_type, refcount, refcount->destroy.cb_arg, val,
val + 1, reason);
}
#else #else
void grpc_stream_ref(grpc_stream_refcount *refcount) { void grpc_stream_ref(grpc_stream_refcount *refcount) {
#endif #endif
gpr_ref_non_zero(&refcount->refs); gpr_ref_non_zero(&refcount->refs);
} }
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount, void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount,
const char *reason) { const char *reason) {
gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count); if (GRPC_TRACER_ON(grpc_trace_stream_refcount)) {
gpr_log(GPR_DEBUG, "%s %p:%p UNREF %" PRIdPTR "->%" PRIdPTR " %s", gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count);
refcount->object_type, refcount, refcount->destroy.cb_arg, val, gpr_log(GPR_DEBUG, "%s %p:%p UNREF %" PRIdPTR "->%" PRIdPTR " %s",
val - 1, reason); refcount->object_type, refcount, refcount->destroy.cb_arg, val,
val - 1, reason);
}
#else #else
void grpc_stream_unref(grpc_exec_ctx *exec_ctx, void grpc_stream_unref(grpc_exec_ctx *exec_ctx,
grpc_stream_refcount *refcount) { grpc_stream_refcount *refcount) {
@ -74,7 +82,7 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx,
offsetof(grpc_stream_refcount, slice_refcount))) offsetof(grpc_stream_refcount, slice_refcount)))
static void slice_stream_ref(void *p) { static void slice_stream_ref(void *p) {
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p), "slice"); grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p), "slice");
#else #else
grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p)); grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p));
@ -82,7 +90,7 @@ static void slice_stream_ref(void *p) {
} }
static void slice_stream_unref(grpc_exec_ctx *exec_ctx, void *p) { static void slice_stream_unref(grpc_exec_ctx *exec_ctx, void *p) {
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p), "slice"); grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p), "slice");
#else #else
grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p)); grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p));
@ -102,7 +110,7 @@ static const grpc_slice_refcount_vtable stream_ref_slice_vtable = {
.eq = grpc_slice_default_eq_impl, .eq = grpc_slice_default_eq_impl,
.hash = grpc_slice_default_hash_impl}; .hash = grpc_slice_default_hash_impl};
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs, void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
grpc_iomgr_cb_func cb, void *cb_arg, grpc_iomgr_cb_func cb, void *cb_arg,
const char *object_type) { const char *object_type) {
@ -198,6 +206,11 @@ grpc_endpoint *grpc_transport_get_endpoint(grpc_exec_ctx *exec_ctx,
return transport->vtable->get_endpoint(exec_ctx, transport); return transport->vtable->get_endpoint(exec_ctx, transport);
} }
// grpc_transport_stream_op_batch_finish_with_failure
// is a function that must always unref cancel_error
// though it lives in lib, it handles transport stream ops sure
// it's grpc_transport_stream_op_batch_finish_with_failure
void grpc_transport_stream_op_batch_finish_with_failure( void grpc_transport_stream_op_batch_finish_with_failure(
grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op, grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op,
grpc_error *error) { grpc_error *error) {

@ -42,18 +42,20 @@ typedef struct grpc_transport grpc_transport;
for a stream. */ for a stream. */
typedef struct grpc_stream grpc_stream; typedef struct grpc_stream grpc_stream;
//#define GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
extern grpc_tracer_flag grpc_trace_stream_refcount;
#endif
typedef struct grpc_stream_refcount { typedef struct grpc_stream_refcount {
gpr_refcount refs; gpr_refcount refs;
grpc_closure destroy; grpc_closure destroy;
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
const char *object_type; const char *object_type;
#endif #endif
grpc_slice_refcount slice_refcount; grpc_slice_refcount slice_refcount;
} grpc_stream_refcount; } grpc_stream_refcount;
#ifdef GRPC_STREAM_REFCOUNT_DEBUG #ifndef NDEBUG
void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs, void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
grpc_iomgr_cb_func cb, void *cb_arg, grpc_iomgr_cb_func cb, void *cb_arg,
const char *object_type); const char *object_type);
@ -165,6 +167,10 @@ struct grpc_transport_stream_op_batch_payload {
uint32_t *recv_flags; uint32_t *recv_flags;
/** Should be enqueued when initial metadata is ready to be processed. */ /** Should be enqueued when initial metadata is ready to be processed. */
grpc_closure *recv_initial_metadata_ready; grpc_closure *recv_initial_metadata_ready;
// If not NULL, will be set to true if trailing metadata is
// immediately available. This may be a signal that we received a
// Trailers-Only response.
bool *trailing_metadata_available;
} recv_initial_metadata; } recv_initial_metadata;
struct { struct {
@ -192,6 +198,8 @@ struct grpc_transport_stream_op_batch_payload {
grpc_chttp2_grpc_status_to_http2_error. Send a RST_STREAM with this grpc_chttp2_grpc_status_to_http2_error. Send a RST_STREAM with this
error. */ error. */
struct { struct {
// Error contract: the transport that gets this op must cause cancel_error
// to be unref'ed after processing it
grpc_error *cancel_error; grpc_error *cancel_error;
} cancel_stream; } cancel_stream;
@ -206,9 +214,13 @@ typedef struct grpc_transport_op {
/** connectivity monitoring - set connectivity_state to NULL to unsubscribe */ /** connectivity monitoring - set connectivity_state to NULL to unsubscribe */
grpc_closure *on_connectivity_state_change; grpc_closure *on_connectivity_state_change;
grpc_connectivity_state *connectivity_state; grpc_connectivity_state *connectivity_state;
/** should the transport be disconnected */ /** should the transport be disconnected
* Error contract: the transport that gets this op must cause
* disconnect_with_error to be unref'ed after processing it */
grpc_error *disconnect_with_error; grpc_error *disconnect_with_error;
/** what should the goaway contain? */ /** what should the goaway contain?
* Error contract: the transport that gets this op must cause
* goaway_error to be unref'ed after processing it */
grpc_error *goaway_error; grpc_error *goaway_error;
/** set the callback for accepting new streams; /** set the callback for accepting new streams;
this is a permanent callback, unlike the other one-shot closures. this is a permanent callback, unlike the other one-shot closures.

@ -208,38 +208,45 @@ class TransportStreamOpBatch {
/// Represents channel data. /// Represents channel data.
class ChannelData { class ChannelData {
public: public:
ChannelData() {}
virtual ~ChannelData() {} virtual ~ChannelData() {}
/// Initializes the call data. // TODO(roth): Come up with a more C++-like API for the channel element.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx,
/// Initializes the channel data.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_channel_element_args *args) { grpc_channel_element_args *args) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
// TODO(roth): Find a way to avoid passing elem into these methods. // Called before destruction.
virtual void Destroy(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {}
virtual void StartTransportOp(grpc_exec_ctx *exec_ctx, virtual void StartTransportOp(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, TransportOp *op); grpc_channel_element *elem, TransportOp *op);
virtual void GetInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, virtual void GetInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
const grpc_channel_info *channel_info); const grpc_channel_info *channel_info);
protected:
ChannelData() {}
}; };
/// Represents call data. /// Represents call data.
class CallData { class CallData {
public: public:
CallData() {}
virtual ~CallData() {} virtual ~CallData() {}
// TODO(roth): Come up with a more C++-like API for the call element.
/// Initializes the call data. /// Initializes the call data.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, ChannelData *channel_data, virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_element_args *args) { const grpc_call_element_args *args) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
// TODO(roth): Find a way to avoid passing elem into these methods. // Called before destruction.
virtual void Destroy(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
grpc_closure *then_call_closure) {}
/// Starts a new stream operation. /// Starts a new stream operation.
virtual void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx, virtual void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx,
@ -253,9 +260,6 @@ class CallData {
/// Gets the peer name. /// Gets the peer name.
virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem); virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
protected:
CallData() {}
}; };
namespace internal { namespace internal {
@ -271,19 +275,24 @@ class ChannelFilter final {
static grpc_error *InitChannelElement(grpc_exec_ctx *exec_ctx, static grpc_error *InitChannelElement(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,
grpc_channel_element_args *args) { grpc_channel_element_args *args) {
// Construct the object in the already-allocated memory.
ChannelDataType *channel_data = new (elem->channel_data) ChannelDataType(); ChannelDataType *channel_data = new (elem->channel_data) ChannelDataType();
return channel_data->Init(exec_ctx, args); return channel_data->Init(exec_ctx, elem, args);
} }
static void DestroyChannelElement(grpc_exec_ctx *exec_ctx, static void DestroyChannelElement(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) { grpc_channel_element *elem) {
reinterpret_cast<ChannelDataType *>(elem->channel_data)->~ChannelDataType(); ChannelDataType *channel_data =
reinterpret_cast<ChannelDataType *>(elem->channel_data);
channel_data->Destroy(exec_ctx, elem);
channel_data->~ChannelDataType();
} }
static void StartTransportOp(grpc_exec_ctx *exec_ctx, static void StartTransportOp(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,
grpc_transport_op *op) { grpc_transport_op *op) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; ChannelDataType *channel_data =
reinterpret_cast<ChannelDataType *>(elem->channel_data);
TransportOp op_wrapper(op); TransportOp op_wrapper(op);
channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper); channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper);
} }
@ -291,7 +300,8 @@ class ChannelFilter final {
static void GetChannelInfo(grpc_exec_ctx *exec_ctx, static void GetChannelInfo(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel_element *elem,
const grpc_channel_info *channel_info) { const grpc_channel_info *channel_info) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; ChannelDataType *channel_data =
reinterpret_cast<ChannelDataType *>(elem->channel_data);
channel_data->GetInfo(exec_ctx, elem, channel_info); channel_data->GetInfo(exec_ctx, elem, channel_info);
} }
@ -300,24 +310,24 @@ class ChannelFilter final {
static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx, static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_element_args *args) { const grpc_call_element_args *args) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
// Construct the object in the already-allocated memory. // Construct the object in the already-allocated memory.
CallDataType *call_data = new (elem->call_data) CallDataType(); CallDataType *call_data = new (elem->call_data) CallDataType();
return call_data->Init(exec_ctx, channel_data, args); return call_data->Init(exec_ctx, elem, args);
} }
static void DestroyCallElement(grpc_exec_ctx *exec_ctx, static void DestroyCallElement(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
const grpc_call_final_info *final_info, const grpc_call_final_info *final_info,
grpc_closure *then_call_closure) { grpc_closure *then_call_closure) {
GPR_ASSERT(then_call_closure == NULL); CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType(); call_data->Destroy(exec_ctx, elem, final_info, then_call_closure);
call_data->~CallDataType();
} }
static void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx, static void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_transport_stream_op_batch *op) { grpc_transport_stream_op_batch *op) {
CallDataType *call_data = (CallDataType *)elem->call_data; CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
TransportStreamOpBatch op_wrapper(op); TransportStreamOpBatch op_wrapper(op);
call_data->StartTransportStreamOpBatch(exec_ctx, elem, &op_wrapper); call_data->StartTransportStreamOpBatch(exec_ctx, elem, &op_wrapper);
} }
@ -325,12 +335,12 @@ class ChannelFilter final {
static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_polling_entity *pollent) { grpc_polling_entity *pollent) {
CallDataType *call_data = (CallDataType *)elem->call_data; CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent); call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent);
} }
static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
CallDataType *call_data = (CallDataType *)elem->call_data; CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
return call_data->GetPeer(exec_ctx, elem); return call_data->GetPeer(exec_ctx, elem);
} }
}; };

@ -17,6 +17,7 @@
#endregion #endregion
using System; using System;
using System.IO;
using System.Linq; using System.Linq;
using Grpc.Core; using Grpc.Core;
using Grpc.Core.Internal; using Grpc.Core.Internal;
@ -65,6 +66,21 @@ namespace Grpc.Core.Tests
server.ShutdownAsync().Wait(); server.ShutdownAsync().Wait();
} }
[Test]
public void StartThrowsWithUnboundPorts()
{
int twiceBoundPort = 9999;
Server server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
{
Ports = {
new ServerPort("localhost", twiceBoundPort, ServerCredentials.Insecure),
new ServerPort("localhost", twiceBoundPort, ServerCredentials.Insecure)
}
};
Assert.Throws(typeof(IOException), () => server.Start());
server.ShutdownAsync().Wait();
}
[Test] [Test]
public void CannotModifyAfterStarted() public void CannotModifyAfterStarted()
{ {

@ -19,6 +19,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Grpc.Core.Internal; using Grpc.Core.Internal;
@ -140,6 +141,7 @@ namespace Grpc.Core
/// <summary> /// <summary>
/// Starts the server. /// Starts the server.
/// Throws <c>IOException</c> if not successful.
/// </summary> /// </summary>
public void Start() public void Start()
{ {
@ -148,7 +150,8 @@ namespace Grpc.Core
GrpcPreconditions.CheckState(!startRequested); GrpcPreconditions.CheckState(!startRequested);
GrpcPreconditions.CheckState(!shutdownRequested); GrpcPreconditions.CheckState(!shutdownRequested);
startRequested = true; startRequested = true;
CheckPortsBoundSuccessfully();
handle.Start(); handle.Start();
for (int i = 0; i < requestCallTokensPerCq; i++) for (int i = 0; i < requestCallTokensPerCq; i++)
@ -301,6 +304,22 @@ namespace Grpc.Core
} }
} }
/// <summary>
/// Checks that all ports have been bound successfully.
/// </summary>
private void CheckPortsBoundSuccessfully()
{
lock (myLock)
{
var unboundPort = ports.FirstOrDefault(port => port.BoundPort == 0);
if (unboundPort != null)
{
throw new IOException(
string.Format("Failed to bind port \"{0}:{1}\"", unboundPort.Host, unboundPort.Port));
}
}
}
private void DisposeHandle() private void DisposeHandle()
{ {
var activeCallCount = activeCallCounter.Count; var activeCallCount = activeCallCounter.Count;

@ -32,7 +32,7 @@ namespace Grpc.Testing {
"U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy", "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
"X2hvc3Rfb3ZlcnJpZGUYAiABKAkiTQoKQ2hhbm5lbEFyZxIMCgRuYW1lGAEg", "X2hvc3Rfb3ZlcnJpZGUYAiABKAkiTQoKQ2hhbm5lbEFyZxIMCgRuYW1lGAEg",
"ASgJEhMKCXN0cl92YWx1ZRgCIAEoCUgAEhMKCWludF92YWx1ZRgDIAEoBUgA", "ASgJEhMKCXN0cl92YWx1ZRgCIAEoCUgAEhMKCWludF92YWx1ZRgDIAEoBUgA",
"QgcKBXZhbHVlIqAECgxDbGllbnRDb25maWcSFgoOc2VydmVyX3RhcmdldHMY", "QgcKBXZhbHVlItUECgxDbGllbnRDb25maWcSFgoOc2VydmVyX3RhcmdldHMY",
"ASADKAkSLQoLY2xpZW50X3R5cGUYAiABKA4yGC5ncnBjLnRlc3RpbmcuQ2xp", "ASADKAkSLQoLY2xpZW50X3R5cGUYAiABKA4yGC5ncnBjLnRlc3RpbmcuQ2xp",
"ZW50VHlwZRI1Cg9zZWN1cml0eV9wYXJhbXMYAyABKAsyHC5ncnBjLnRlc3Rp", "ZW50VHlwZRI1Cg9zZWN1cml0eV9wYXJhbXMYAyABKAsyHC5ncnBjLnRlc3Rp",
"bmcuU2VjdXJpdHlQYXJhbXMSJAocb3V0c3RhbmRpbmdfcnBjc19wZXJfY2hh", "bmcuU2VjdXJpdHlQYXJhbXMSJAocb3V0c3RhbmRpbmdfcnBjc19wZXJfY2hh",
@ -44,52 +44,57 @@ namespace Grpc.Testing {
"cxgMIAEoCzIdLmdycGMudGVzdGluZy5IaXN0b2dyYW1QYXJhbXMSEQoJY29y", "cxgMIAEoCzIdLmdycGMudGVzdGluZy5IaXN0b2dyYW1QYXJhbXMSEQoJY29y",
"ZV9saXN0GA0gAygFEhIKCmNvcmVfbGltaXQYDiABKAUSGAoQb3RoZXJfY2xp", "ZV9saXN0GA0gAygFEhIKCmNvcmVfbGltaXQYDiABKAUSGAoQb3RoZXJfY2xp",
"ZW50X2FwaRgPIAEoCRIuCgxjaGFubmVsX2FyZ3MYECADKAsyGC5ncnBjLnRl", "ZW50X2FwaRgPIAEoCRIuCgxjaGFubmVsX2FyZ3MYECADKAsyGC5ncnBjLnRl",
"c3RpbmcuQ2hhbm5lbEFyZyI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASAB", "c3RpbmcuQ2hhbm5lbEFyZxIWCg50aHJlYWRzX3Blcl9jcRgRIAEoBRIbChNt",
"KAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNl", "ZXNzYWdlc19wZXJfc3RyZWFtGBIgASgFIjgKDENsaWVudFN0YXR1cxIoCgVz",
"dBgBIAEoCCJoCgpDbGllbnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50", "dGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIVCgRNYXJr",
"ZXN0aW5nLkNsaWVudENvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRl", "Eg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAYASABKAsy",
"c3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUitAIKDFNlcnZlckNvbmZpZxItCgtz", "Gi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgCIAEoCzIS",
"ZXJ2ZXJfdHlwZRgBIAEoDjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUK", "LmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSLMAgoMU2VydmVyQ29u",
"D3NlY3VyaXR5X3BhcmFtcxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0", "ZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5nLlNlcnZl",
"eVBhcmFtcxIMCgRwb3J0GAQgASgFEhwKFGFzeW5jX3NlcnZlcl90aHJlYWRz", "clR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50ZXN0aW5n",
"GAcgASgFEhIKCmNvcmVfbGltaXQYCCABKAUSMwoOcGF5bG9hZF9jb25maWcY", "LlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVy",
"CSABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxIRCgljb3JlX2xp", "X3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2Fk",
"c3QYCiADKAUSGAoQb3RoZXJfc2VydmVyX2FwaRgLIAEoCRIcChNyZXNvdXJj", "X2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnEhEK",
"ZV9xdW90YV9zaXplGOkHIAEoBSJoCgpTZXJ2ZXJBcmdzEisKBXNldHVwGAEg", "CWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsgASgJEhYK",
"ASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZ0gAEiIKBG1hcmsYAiAB", "DnRocmVhZHNfcGVyX2NxGAwgASgFEhwKE3Jlc291cmNlX3F1b3RhX3NpemUY",
"KAsyEi5ncnBjLnRlc3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUiVQoMU2VydmVy", "6QcgASgFImgKClNlcnZlckFyZ3MSKwoFc2V0dXAYASABKAsyGi5ncnBjLnRl",
"U3RhdHVzEigKBXN0YXRzGAEgASgLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0", "c3RpbmcuU2VydmVyQ29uZmlnSAASIgoEbWFyaxgCIAEoCzISLmdycGMudGVz",
"YXRzEgwKBHBvcnQYAiABKAUSDQoFY29yZXMYAyABKAUiDQoLQ29yZVJlcXVl", "dGluZy5NYXJrSABCCQoHYXJndHlwZSJVCgxTZXJ2ZXJTdGF0dXMSKAoFc3Rh",
"c3QiHQoMQ29yZVJlc3BvbnNlEg0KBWNvcmVzGAEgASgFIgYKBFZvaWQi/QEK", "dHMYASABKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSDAoEcG9ydBgC",
"CFNjZW5hcmlvEgwKBG5hbWUYASABKAkSMQoNY2xpZW50X2NvbmZpZxgCIAEo", "IAEoBRINCgVjb3JlcxgDIAEoBSINCgtDb3JlUmVxdWVzdCIdCgxDb3JlUmVz",
"CzIaLmdycGMudGVzdGluZy5DbGllbnRDb25maWcSEwoLbnVtX2NsaWVudHMY", "cG9uc2USDQoFY29yZXMYASABKAUiBgoEVm9pZCL9AQoIU2NlbmFyaW8SDAoE",
"AyABKAUSMQoNc2VydmVyX2NvbmZpZxgEIAEoCzIaLmdycGMudGVzdGluZy5T", "bmFtZRgBIAEoCRIxCg1jbGllbnRfY29uZmlnGAIgASgLMhouZ3JwYy50ZXN0",
"ZXJ2ZXJDb25maWcSEwoLbnVtX3NlcnZlcnMYBSABKAUSFgoOd2FybXVwX3Nl", "aW5nLkNsaWVudENvbmZpZxITCgtudW1fY2xpZW50cxgDIAEoBRIxCg1zZXJ2",
"Y29uZHMYBiABKAUSGQoRYmVuY2htYXJrX3NlY29uZHMYByABKAUSIAoYc3Bh", "ZXJfY29uZmlnGAQgASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZxIT",
"d25fbG9jYWxfd29ya2VyX2NvdW50GAggASgFIjYKCVNjZW5hcmlvcxIpCglz", "CgtudW1fc2VydmVycxgFIAEoBRIWCg53YXJtdXBfc2Vjb25kcxgGIAEoBRIZ",
"Y2VuYXJpb3MYASADKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8i+AIKFVNj", "ChFiZW5jaG1hcmtfc2Vjb25kcxgHIAEoBRIgChhzcGF3bl9sb2NhbF93b3Jr",
"ZW5hcmlvUmVzdWx0U3VtbWFyeRILCgNxcHMYASABKAESGwoTcXBzX3Blcl9z", "ZXJfY291bnQYCCABKAUiNgoJU2NlbmFyaW9zEikKCXNjZW5hcmlvcxgBIAMo",
"ZXJ2ZXJfY29yZRgCIAEoARIaChJzZXJ2ZXJfc3lzdGVtX3RpbWUYAyABKAES", "CzIWLmdycGMudGVzdGluZy5TY2VuYXJpbyK8AwoVU2NlbmFyaW9SZXN1bHRT",
"GAoQc2VydmVyX3VzZXJfdGltZRgEIAEoARIaChJjbGllbnRfc3lzdGVtX3Rp", "dW1tYXJ5EgsKA3FwcxgBIAEoARIbChNxcHNfcGVyX3NlcnZlcl9jb3JlGAIg",
"bWUYBSABKAESGAoQY2xpZW50X3VzZXJfdGltZRgGIAEoARISCgpsYXRlbmN5", "ASgBEhoKEnNlcnZlcl9zeXN0ZW1fdGltZRgDIAEoARIYChBzZXJ2ZXJfdXNl",
"XzUwGAcgASgBEhIKCmxhdGVuY3lfOTAYCCABKAESEgoKbGF0ZW5jeV85NRgJ", "cl90aW1lGAQgASgBEhoKEmNsaWVudF9zeXN0ZW1fdGltZRgFIAEoARIYChBj",
"IAEoARISCgpsYXRlbmN5Xzk5GAogASgBEhMKC2xhdGVuY3lfOTk5GAsgASgB", "bGllbnRfdXNlcl90aW1lGAYgASgBEhIKCmxhdGVuY3lfNTAYByABKAESEgoK",
"EhgKEHNlcnZlcl9jcHVfdXNhZ2UYDCABKAESJgoec3VjY2Vzc2Z1bF9yZXF1", "bGF0ZW5jeV85MBgIIAEoARISCgpsYXRlbmN5Xzk1GAkgASgBEhIKCmxhdGVu",
"ZXN0c19wZXJfc2Vjb25kGA0gASgBEiIKGmZhaWxlZF9yZXF1ZXN0c19wZXJf", "Y3lfOTkYCiABKAESEwoLbGF0ZW5jeV85OTkYCyABKAESGAoQc2VydmVyX2Nw",
"c2Vjb25kGA4gASgBIoMDCg5TY2VuYXJpb1Jlc3VsdBIoCghzY2VuYXJpbxgB", "dV91c2FnZRgMIAEoARImCh5zdWNjZXNzZnVsX3JlcXVlc3RzX3Blcl9zZWNv",
"IAEoCzIWLmdycGMudGVzdGluZy5TY2VuYXJpbxIuCglsYXRlbmNpZXMYAiAB", "bmQYDSABKAESIgoaZmFpbGVkX3JlcXVlc3RzX3Blcl9zZWNvbmQYDiABKAES",
"KAsyGy5ncnBjLnRlc3RpbmcuSGlzdG9ncmFtRGF0YRIvCgxjbGllbnRfc3Rh", "IAoYY2xpZW50X3BvbGxzX3Blcl9yZXF1ZXN0GA8gASgBEiAKGHNlcnZlcl9w",
"dHMYAyADKAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMSLwoMc2VydmVy", "b2xsc19wZXJfcmVxdWVzdBgQIAEoASKDAwoOU2NlbmFyaW9SZXN1bHQSKAoI",
"X3N0YXRzGAQgAygLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXRzEhQKDHNl", "c2NlbmFyaW8YASABKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8SLgoJbGF0",
"cnZlcl9jb3JlcxgFIAMoBRI0CgdzdW1tYXJ5GAYgASgLMiMuZ3JwYy50ZXN0", "ZW5jaWVzGAIgASgLMhsuZ3JwYy50ZXN0aW5nLkhpc3RvZ3JhbURhdGESLwoM",
"aW5nLlNjZW5hcmlvUmVzdWx0U3VtbWFyeRIWCg5jbGllbnRfc3VjY2VzcxgH", "Y2xpZW50X3N0YXRzGAMgAygLMhkuZ3JwYy50ZXN0aW5nLkNsaWVudFN0YXRz",
"IAMoCBIWCg5zZXJ2ZXJfc3VjY2VzcxgIIAMoCBI5Cg9yZXF1ZXN0X3Jlc3Vs", "Ei8KDHNlcnZlcl9zdGF0cxgEIAMoCzIZLmdycGMudGVzdGluZy5TZXJ2ZXJT",
"dHMYCSADKAsyIC5ncnBjLnRlc3RpbmcuUmVxdWVzdFJlc3VsdENvdW50KkEK", "dGF0cxIUCgxzZXJ2ZXJfY29yZXMYBSADKAUSNAoHc3VtbWFyeRgGIAEoCzIj",
"CkNsaWVudFR5cGUSDwoLU1lOQ19DTElFTlQQABIQCgxBU1lOQ19DTElFTlQQ", "LmdycGMudGVzdGluZy5TY2VuYXJpb1Jlc3VsdFN1bW1hcnkSFgoOY2xpZW50",
"ARIQCgxPVEhFUl9DTElFTlQQAipbCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VS", "X3N1Y2Nlc3MYByADKAgSFgoOc2VydmVyX3N1Y2Nlc3MYCCADKAgSOQoPcmVx",
"VkVSEAASEAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJW", "dWVzdF9yZXN1bHRzGAkgAygLMiAuZ3JwYy50ZXN0aW5nLlJlcXVlc3RSZXN1",
"RVIQAhIQCgxPVEhFUl9TRVJWRVIQAyojCgdScGNUeXBlEgkKBVVOQVJZEAAS", "bHRDb3VudCpBCgpDbGllbnRUeXBlEg8KC1NZTkNfQ0xJRU5UEAASEAoMQVNZ",
"DQoJU1RSRUFNSU5HEAFiBnByb3RvMw==")); "TkNfQ0xJRU5UEAESEAoMT1RIRVJfQ0xJRU5UEAIqWwoKU2VydmVyVHlwZRIP",
"CgtTWU5DX1NFUlZFUhAAEhAKDEFTWU5DX1NFUlZFUhABEhgKFEFTWU5DX0dF",
"TkVSSUNfU0VSVkVSEAISEAoMT1RIRVJfU0VSVkVSEAMqcgoHUnBjVHlwZRIJ",
"CgVVTkFSWRAAEg0KCVNUUkVBTUlORxABEhkKFVNUUkVBTUlOR19GUk9NX0NM",
"SUVOVBACEhkKFVNUUkVBTUlOR19GUk9NX1NFUlZFUhADEhcKE1NUUkVBTUlO",
"R19CT1RIX1dBWVMQBGIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, }, new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] {
@ -98,11 +103,11 @@ namespace Grpc.Testing {
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs", "ThreadsPerCq", "MessagesPerStream" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi", "ResourceQuotaSize" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi", "ThreadsPerCq", "ResourceQuotaSize" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null),
@ -110,7 +115,7 @@ namespace Grpc.Testing {
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999", "ServerCpuUsage", "SuccessfulRequestsPerSecond", "FailedRequestsPerSecond" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999", "ServerCpuUsage", "SuccessfulRequestsPerSecond", "FailedRequestsPerSecond", "ClientPollsPerRequest", "ServerPollsPerRequest" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary", "ClientSuccess", "ServerSuccess", "RequestResults" }, null, null, null) new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary", "ClientSuccess", "ServerSuccess", "RequestResults" }, null, null, null)
})); }));
} }
@ -144,6 +149,9 @@ namespace Grpc.Testing {
public enum RpcType { public enum RpcType {
[pbr::OriginalName("UNARY")] Unary = 0, [pbr::OriginalName("UNARY")] Unary = 0,
[pbr::OriginalName("STREAMING")] Streaming = 1, [pbr::OriginalName("STREAMING")] Streaming = 1,
[pbr::OriginalName("STREAMING_FROM_CLIENT")] StreamingFromClient = 2,
[pbr::OriginalName("STREAMING_FROM_SERVER")] StreamingFromServer = 3,
[pbr::OriginalName("STREAMING_BOTH_WAYS")] StreamingBothWays = 4,
} }
#endregion #endregion
@ -942,6 +950,8 @@ namespace Grpc.Testing {
coreLimit_ = other.coreLimit_; coreLimit_ = other.coreLimit_;
otherClientApi_ = other.otherClientApi_; otherClientApi_ = other.otherClientApi_;
channelArgs_ = other.channelArgs_.Clone(); channelArgs_ = other.channelArgs_.Clone();
threadsPerCq_ = other.threadsPerCq_;
messagesPerStream_ = other.messagesPerStream_;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1123,6 +1133,34 @@ namespace Grpc.Testing {
get { return channelArgs_; } get { return channelArgs_; }
} }
/// <summary>Field number for the "threads_per_cq" field.</summary>
public const int ThreadsPerCqFieldNumber = 17;
private int threadsPerCq_;
/// <summary>
/// Number of threads that share each completion queue
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ThreadsPerCq {
get { return threadsPerCq_; }
set {
threadsPerCq_ = value;
}
}
/// <summary>Field number for the "messages_per_stream" field.</summary>
public const int MessagesPerStreamFieldNumber = 18;
private int messagesPerStream_;
/// <summary>
/// Number of messages on a stream before it gets finished/restarted
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int MessagesPerStream {
get { return messagesPerStream_; }
set {
messagesPerStream_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as ClientConfig); return Equals(other as ClientConfig);
@ -1150,6 +1188,8 @@ namespace Grpc.Testing {
if (CoreLimit != other.CoreLimit) return false; if (CoreLimit != other.CoreLimit) return false;
if (OtherClientApi != other.OtherClientApi) return false; if (OtherClientApi != other.OtherClientApi) return false;
if(!channelArgs_.Equals(other.channelArgs_)) return false; if(!channelArgs_.Equals(other.channelArgs_)) return false;
if (ThreadsPerCq != other.ThreadsPerCq) return false;
if (MessagesPerStream != other.MessagesPerStream) return false;
return true; return true;
} }
@ -1170,6 +1210,8 @@ namespace Grpc.Testing {
if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode(); if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode(); if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode();
hash ^= channelArgs_.GetHashCode(); hash ^= channelArgs_.GetHashCode();
if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
if (MessagesPerStream != 0) hash ^= MessagesPerStream.GetHashCode();
return hash; return hash;
} }
@ -1227,6 +1269,14 @@ namespace Grpc.Testing {
output.WriteString(OtherClientApi); output.WriteString(OtherClientApi);
} }
channelArgs_.WriteTo(output, _repeated_channelArgs_codec); channelArgs_.WriteTo(output, _repeated_channelArgs_codec);
if (ThreadsPerCq != 0) {
output.WriteRawTag(136, 1);
output.WriteInt32(ThreadsPerCq);
}
if (MessagesPerStream != 0) {
output.WriteRawTag(144, 1);
output.WriteInt32(MessagesPerStream);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1268,6 +1318,12 @@ namespace Grpc.Testing {
size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi); size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi);
} }
size += channelArgs_.CalculateSize(_repeated_channelArgs_codec); size += channelArgs_.CalculateSize(_repeated_channelArgs_codec);
if (ThreadsPerCq != 0) {
size += 2 + pb::CodedOutputStream.ComputeInt32Size(ThreadsPerCq);
}
if (MessagesPerStream != 0) {
size += 2 + pb::CodedOutputStream.ComputeInt32Size(MessagesPerStream);
}
return size; return size;
} }
@ -1324,6 +1380,12 @@ namespace Grpc.Testing {
OtherClientApi = other.OtherClientApi; OtherClientApi = other.OtherClientApi;
} }
channelArgs_.Add(other.channelArgs_); channelArgs_.Add(other.channelArgs_);
if (other.ThreadsPerCq != 0) {
ThreadsPerCq = other.ThreadsPerCq;
}
if (other.MessagesPerStream != 0) {
MessagesPerStream = other.MessagesPerStream;
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1403,6 +1465,14 @@ namespace Grpc.Testing {
channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec); channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec);
break; break;
} }
case 136: {
ThreadsPerCq = input.ReadInt32();
break;
}
case 144: {
MessagesPerStream = input.ReadInt32();
break;
}
} }
} }
} }
@ -1873,6 +1943,7 @@ namespace Grpc.Testing {
PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null; PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
coreList_ = other.coreList_.Clone(); coreList_ = other.coreList_.Clone();
otherServerApi_ = other.otherServerApi_; otherServerApi_ = other.otherServerApi_;
threadsPerCq_ = other.threadsPerCq_;
resourceQuotaSize_ = other.resourceQuotaSize_; resourceQuotaSize_ = other.resourceQuotaSize_;
} }
@ -1989,6 +2060,20 @@ namespace Grpc.Testing {
} }
} }
/// <summary>Field number for the "threads_per_cq" field.</summary>
public const int ThreadsPerCqFieldNumber = 12;
private int threadsPerCq_;
/// <summary>
/// Number of threads that share each completion queue
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ThreadsPerCq {
get { return threadsPerCq_; }
set {
threadsPerCq_ = value;
}
}
/// <summary>Field number for the "resource_quota_size" field.</summary> /// <summary>Field number for the "resource_quota_size" field.</summary>
public const int ResourceQuotaSizeFieldNumber = 1001; public const int ResourceQuotaSizeFieldNumber = 1001;
private int resourceQuotaSize_; private int resourceQuotaSize_;
@ -2024,6 +2109,7 @@ namespace Grpc.Testing {
if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false; if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
if(!coreList_.Equals(other.coreList_)) return false; if(!coreList_.Equals(other.coreList_)) return false;
if (OtherServerApi != other.OtherServerApi) return false; if (OtherServerApi != other.OtherServerApi) return false;
if (ThreadsPerCq != other.ThreadsPerCq) return false;
if (ResourceQuotaSize != other.ResourceQuotaSize) return false; if (ResourceQuotaSize != other.ResourceQuotaSize) return false;
return true; return true;
} }
@ -2039,6 +2125,7 @@ namespace Grpc.Testing {
if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode(); if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
hash ^= coreList_.GetHashCode(); hash ^= coreList_.GetHashCode();
if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode(); if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode();
if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode(); if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode();
return hash; return hash;
} }
@ -2079,6 +2166,10 @@ namespace Grpc.Testing {
output.WriteRawTag(90); output.WriteRawTag(90);
output.WriteString(OtherServerApi); output.WriteString(OtherServerApi);
} }
if (ThreadsPerCq != 0) {
output.WriteRawTag(96);
output.WriteInt32(ThreadsPerCq);
}
if (ResourceQuotaSize != 0) { if (ResourceQuotaSize != 0) {
output.WriteRawTag(200, 62); output.WriteRawTag(200, 62);
output.WriteInt32(ResourceQuotaSize); output.WriteInt32(ResourceQuotaSize);
@ -2110,6 +2201,9 @@ namespace Grpc.Testing {
if (OtherServerApi.Length != 0) { if (OtherServerApi.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi); size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi);
} }
if (ThreadsPerCq != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ThreadsPerCq);
}
if (ResourceQuotaSize != 0) { if (ResourceQuotaSize != 0) {
size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize); size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize);
} }
@ -2149,6 +2243,9 @@ namespace Grpc.Testing {
if (other.OtherServerApi.Length != 0) { if (other.OtherServerApi.Length != 0) {
OtherServerApi = other.OtherServerApi; OtherServerApi = other.OtherServerApi;
} }
if (other.ThreadsPerCq != 0) {
ThreadsPerCq = other.ThreadsPerCq;
}
if (other.ResourceQuotaSize != 0) { if (other.ResourceQuotaSize != 0) {
ResourceQuotaSize = other.ResourceQuotaSize; ResourceQuotaSize = other.ResourceQuotaSize;
} }
@ -2201,6 +2298,10 @@ namespace Grpc.Testing {
OtherServerApi = input.ReadString(); OtherServerApi = input.ReadString();
break; break;
} }
case 96: {
ThreadsPerCq = input.ReadInt32();
break;
}
case 8008: { case 8008: {
ResourceQuotaSize = input.ReadInt32(); ResourceQuotaSize = input.ReadInt32();
break; break;
@ -3386,6 +3487,8 @@ namespace Grpc.Testing {
serverCpuUsage_ = other.serverCpuUsage_; serverCpuUsage_ = other.serverCpuUsage_;
successfulRequestsPerSecond_ = other.successfulRequestsPerSecond_; successfulRequestsPerSecond_ = other.successfulRequestsPerSecond_;
failedRequestsPerSecond_ = other.failedRequestsPerSecond_; failedRequestsPerSecond_ = other.failedRequestsPerSecond_;
clientPollsPerRequest_ = other.clientPollsPerRequest_;
serverPollsPerRequest_ = other.serverPollsPerRequest_;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3574,6 +3677,31 @@ namespace Grpc.Testing {
} }
} }
/// <summary>Field number for the "client_polls_per_request" field.</summary>
public const int ClientPollsPerRequestFieldNumber = 15;
private double clientPollsPerRequest_;
/// <summary>
/// Number of polls called inside completion queue per request
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ClientPollsPerRequest {
get { return clientPollsPerRequest_; }
set {
clientPollsPerRequest_ = value;
}
}
/// <summary>Field number for the "server_polls_per_request" field.</summary>
public const int ServerPollsPerRequestFieldNumber = 16;
private double serverPollsPerRequest_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ServerPollsPerRequest {
get { return serverPollsPerRequest_; }
set {
serverPollsPerRequest_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as ScenarioResultSummary); return Equals(other as ScenarioResultSummary);
@ -3601,6 +3729,8 @@ namespace Grpc.Testing {
if (ServerCpuUsage != other.ServerCpuUsage) return false; if (ServerCpuUsage != other.ServerCpuUsage) return false;
if (SuccessfulRequestsPerSecond != other.SuccessfulRequestsPerSecond) return false; if (SuccessfulRequestsPerSecond != other.SuccessfulRequestsPerSecond) return false;
if (FailedRequestsPerSecond != other.FailedRequestsPerSecond) return false; if (FailedRequestsPerSecond != other.FailedRequestsPerSecond) return false;
if (ClientPollsPerRequest != other.ClientPollsPerRequest) return false;
if (ServerPollsPerRequest != other.ServerPollsPerRequest) return false;
return true; return true;
} }
@ -3621,6 +3751,8 @@ namespace Grpc.Testing {
if (ServerCpuUsage != 0D) hash ^= ServerCpuUsage.GetHashCode(); if (ServerCpuUsage != 0D) hash ^= ServerCpuUsage.GetHashCode();
if (SuccessfulRequestsPerSecond != 0D) hash ^= SuccessfulRequestsPerSecond.GetHashCode(); if (SuccessfulRequestsPerSecond != 0D) hash ^= SuccessfulRequestsPerSecond.GetHashCode();
if (FailedRequestsPerSecond != 0D) hash ^= FailedRequestsPerSecond.GetHashCode(); if (FailedRequestsPerSecond != 0D) hash ^= FailedRequestsPerSecond.GetHashCode();
if (ClientPollsPerRequest != 0D) hash ^= ClientPollsPerRequest.GetHashCode();
if (ServerPollsPerRequest != 0D) hash ^= ServerPollsPerRequest.GetHashCode();
return hash; return hash;
} }
@ -3687,6 +3819,14 @@ namespace Grpc.Testing {
output.WriteRawTag(113); output.WriteRawTag(113);
output.WriteDouble(FailedRequestsPerSecond); output.WriteDouble(FailedRequestsPerSecond);
} }
if (ClientPollsPerRequest != 0D) {
output.WriteRawTag(121);
output.WriteDouble(ClientPollsPerRequest);
}
if (ServerPollsPerRequest != 0D) {
output.WriteRawTag(129, 1);
output.WriteDouble(ServerPollsPerRequest);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3734,6 +3874,12 @@ namespace Grpc.Testing {
if (FailedRequestsPerSecond != 0D) { if (FailedRequestsPerSecond != 0D) {
size += 1 + 8; size += 1 + 8;
} }
if (ClientPollsPerRequest != 0D) {
size += 1 + 8;
}
if (ServerPollsPerRequest != 0D) {
size += 2 + 8;
}
return size; return size;
} }
@ -3784,6 +3930,12 @@ namespace Grpc.Testing {
if (other.FailedRequestsPerSecond != 0D) { if (other.FailedRequestsPerSecond != 0D) {
FailedRequestsPerSecond = other.FailedRequestsPerSecond; FailedRequestsPerSecond = other.FailedRequestsPerSecond;
} }
if (other.ClientPollsPerRequest != 0D) {
ClientPollsPerRequest = other.ClientPollsPerRequest;
}
if (other.ServerPollsPerRequest != 0D) {
ServerPollsPerRequest = other.ServerPollsPerRequest;
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3850,6 +4002,14 @@ namespace Grpc.Testing {
FailedRequestsPerSecond = input.ReadDouble(); FailedRequestsPerSecond = input.ReadDouble();
break; break;
} }
case 121: {
ClientPollsPerRequest = input.ReadDouble();
break;
}
case 129: {
ServerPollsPerRequest = input.ReadDouble();
break;
}
} }
} }
} }

@ -0,0 +1,112 @@
#region Copyright notice and license
// Copyright 2015-2016 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
{
/// <summary>
/// Shows how to attach custom error details as a binary trailer.
/// </summary>
public class CustomErrorDetailsTest
{
const string DebugInfoTrailerName = "debug-info-bin";
const string ExceptionDetail = "Exception thrown on purpose.";
const string Host = "localhost";
Server server;
Channel channel;
TestService.TestServiceClient client;
[TestFixtureSetUp]
public void Init()
{
// Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755
server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
{
Services = { TestService.BindService(new CustomErrorDetailsTestServiceImpl()) },
Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
};
server.Start();
channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
client = new TestService.TestServiceClient(channel);
}
[TestFixtureTearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
[Test]
public async Task UnaryCall()
{
var call = client.UnaryCallAsync(new SimpleRequest { ResponseSize = 10 });
try
{
await call.ResponseAsync;
Assert.Fail();
}
catch (RpcException e)
{
Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
var debugInfo = GetDebugInfo(call.GetTrailers());
Assert.AreEqual(debugInfo.Detail, ExceptionDetail);
Assert.IsNotEmpty(debugInfo.StackEntries);
}
}
private DebugInfo GetDebugInfo(Metadata trailers)
{
var entry = trailers.First((e) => e.Key == DebugInfoTrailerName);
return DebugInfo.Parser.ParseFrom(entry.ValueBytes);
}
private class CustomErrorDetailsTestServiceImpl : TestService.TestServiceBase
{
public override async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
{
try
{
throw new ArgumentException(ExceptionDetail);
}
catch (Exception e)
{
// Fill debug info with some structured details about the failure.
var debugInfo = new DebugInfo();
debugInfo.Detail = e.Message;
debugInfo.StackEntries.AddRange(e.StackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None));
context.ResponseTrailers.Add(DebugInfoTrailerName, debugInfo.ToByteArray());
throw new RpcException(new Status(StatusCode.Unknown, "The handler threw exception."));
}
}
}
}
}

File diff suppressed because it is too large Load Diff

@ -24,20 +24,28 @@ namespace Grpc.Testing {
string.Concat( string.Concat(
"CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3NlcnZpY2VzLnByb3RvEgxncnBj", "CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3NlcnZpY2VzLnByb3RvEgxncnBj",
"LnRlc3RpbmcaJXNyYy9wcm90by9ncnBjL3Rlc3RpbmcvbWVzc2FnZXMucHJv", "LnRlc3RpbmcaJXNyYy9wcm90by9ncnBjL3Rlc3RpbmcvbWVzc2FnZXMucHJv",
"dG8aJHNyYy9wcm90by9ncnBjL3Rlc3RpbmcvY29udHJvbC5wcm90bzKqAQoQ", "dG8aJHNyYy9wcm90by9ncnBjL3Rlc3RpbmcvY29udHJvbC5wcm90bxoic3Jj",
"QmVuY2htYXJrU2VydmljZRJGCglVbmFyeUNhbGwSGy5ncnBjLnRlc3Rpbmcu", "L3Byb3RvL2dycGMvdGVzdGluZy9zdGF0cy5wcm90bzKmAwoQQmVuY2htYXJr",
"U2ltcGxlUmVxdWVzdBocLmdycGMudGVzdGluZy5TaW1wbGVSZXNwb25zZRJO", "U2VydmljZRJGCglVbmFyeUNhbGwSGy5ncnBjLnRlc3RpbmcuU2ltcGxlUmVx",
"Cg1TdHJlYW1pbmdDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3Qa", "dWVzdBocLmdycGMudGVzdGluZy5TaW1wbGVSZXNwb25zZRJOCg1TdHJlYW1p",
"HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UoATABMpcCCg1Xb3JrZXJT", "bmdDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3QaHC5ncnBjLnRl",
"ZXJ2aWNlEkUKCVJ1blNlcnZlchIYLmdycGMudGVzdGluZy5TZXJ2ZXJBcmdz", "c3RpbmcuU2ltcGxlUmVzcG9uc2UoATABElIKE1N0cmVhbWluZ0Zyb21DbGll",
"GhouZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXR1cygBMAESRQoJUnVuQ2xpZW50", "bnQSGy5ncnBjLnRlc3RpbmcuU2ltcGxlUmVxdWVzdBocLmdycGMudGVzdGlu",
"EhguZ3JwYy50ZXN0aW5nLkNsaWVudEFyZ3MaGi5ncnBjLnRlc3RpbmcuQ2xp", "Zy5TaW1wbGVSZXNwb25zZSgBElIKE1N0cmVhbWluZ0Zyb21TZXJ2ZXISGy5n",
"ZW50U3RhdHVzKAEwARJCCglDb3JlQ291bnQSGS5ncnBjLnRlc3RpbmcuQ29y", "cnBjLnRlc3RpbmcuU2ltcGxlUmVxdWVzdBocLmdycGMudGVzdGluZy5TaW1w",
"ZVJlcXVlc3QaGi5ncnBjLnRlc3RpbmcuQ29yZVJlc3BvbnNlEjQKClF1aXRX", "bGVSZXNwb25zZTABElIKEVN0cmVhbWluZ0JvdGhXYXlzEhsuZ3JwYy50ZXN0",
"b3JrZXISEi5ncnBjLnRlc3RpbmcuVm9pZBoSLmdycGMudGVzdGluZy5Wb2lk", "aW5nLlNpbXBsZVJlcXVlc3QaHC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9u",
"YgZwcm90bzM=")); "c2UoATABMpcCCg1Xb3JrZXJTZXJ2aWNlEkUKCVJ1blNlcnZlchIYLmdycGMu",
"dGVzdGluZy5TZXJ2ZXJBcmdzGhouZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXR1",
"cygBMAESRQoJUnVuQ2xpZW50EhguZ3JwYy50ZXN0aW5nLkNsaWVudEFyZ3Ma",
"Gi5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHVzKAEwARJCCglDb3JlQ291bnQS",
"GS5ncnBjLnRlc3RpbmcuQ29yZVJlcXVlc3QaGi5ncnBjLnRlc3RpbmcuQ29y",
"ZVJlc3BvbnNlEjQKClF1aXRXb3JrZXISEi5ncnBjLnRlc3RpbmcuVm9pZBoS",
"LmdycGMudGVzdGluZy5Wb2lkMl4KGFJlcG9ydFFwc1NjZW5hcmlvU2Vydmlj",
"ZRJCCg5SZXBvcnRTY2VuYXJpbxIcLmdycGMudGVzdGluZy5TY2VuYXJpb1Jl",
"c3VsdBoSLmdycGMudGVzdGluZy5Wb2lkYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, global::Grpc.Testing.ControlReflection.Descriptor, }, new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, global::Grpc.Testing.ControlReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(null, null)); new pbr::GeneratedClrTypeInfo(null, null));
} }
#endregion #endregion

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save