Merge branch 'master' into feature/qps-bazel-test

pull/16402/head
Bill Feng 7 years ago
commit b47406a488
  1. 2
      .pylintrc-tests
  2. 10
      BUILD
  3. 3
      BUILDING.md
  4. 6
      build.yaml
  5. 9
      cmake/ssl.cmake
  6. 8
      doc/core/grpc-error.md
  7. 3
      doc/cpp/pending_api_cleanups.md
  8. 4
      doc/ssl-performance.md
  9. 8
      examples/csharp/Helloworld/Greeter/Greeter.csproj
  10. 38
      examples/csharp/Helloworld/Greeter/Helloworld.cs
  11. 23
      examples/csharp/Helloworld/Greeter/HelloworldGrpc.cs
  12. 5
      examples/csharp/Helloworld/generate_protos.bat
  13. 19
      examples/csharp/HelloworldLegacyCsproj/Greeter/Greeter.csproj
  14. 38
      examples/csharp/HelloworldLegacyCsproj/Greeter/Helloworld.cs
  15. 23
      examples/csharp/HelloworldLegacyCsproj/Greeter/HelloworldGrpc.cs
  16. 8
      examples/csharp/HelloworldLegacyCsproj/Greeter/packages.config
  17. 19
      examples/csharp/HelloworldLegacyCsproj/GreeterClient/GreeterClient.csproj
  18. 6
      examples/csharp/HelloworldLegacyCsproj/GreeterClient/packages.config
  19. 19
      examples/csharp/HelloworldLegacyCsproj/GreeterServer/GreeterServer.csproj
  20. 6
      examples/csharp/HelloworldLegacyCsproj/GreeterServer/packages.config
  21. 2
      examples/csharp/HelloworldLegacyCsproj/generate_protos.bat
  22. 94
      examples/csharp/RouteGuide/RouteGuide/RouteGuide.cs
  23. 8
      examples/csharp/RouteGuide/RouteGuide/RouteGuide.csproj
  24. 47
      examples/csharp/RouteGuide/RouteGuide/RouteGuideGrpc.cs
  25. 6
      examples/csharp/RouteGuide/generate_protos.bat
  26. 1
      gRPC-C++.podspec
  27. 5
      gRPC-Core.podspec
  28. 1
      grpc.def
  29. 1
      grpc.gemspec
  30. 6
      include/grpc/grpc.h
  31. 41
      include/grpc/impl/codegen/port_platform.h
  32. 37
      include/grpcpp/impl/codegen/service_type.h
  33. 11
      include/grpcpp/opencensus.h
  34. 1
      package.xml
  35. 2
      src/core/ext/filters/client_channel/client_channel.cc
  36. 5
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  37. 2
      src/core/ext/filters/http/client_authority_filter.cc
  38. 7
      src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
  39. 77
      src/core/lib/gpr/arena.cc
  40. 74
      src/core/lib/gprpp/fork.cc
  41. 17
      src/core/lib/gprpp/fork.h
  42. 72
      src/core/lib/iomgr/ev_epoll1_linux.cc
  43. 7
      src/core/lib/iomgr/ev_posix.cc
  44. 6
      src/core/lib/iomgr/exec_ctx.cc
  45. 2
      src/core/lib/iomgr/exec_ctx.h
  46. 7
      src/core/lib/iomgr/fork_posix.cc
  47. 12
      src/core/lib/iomgr/port.h
  48. 2
      src/core/lib/iomgr/socket_mutator.cc
  49. 2
      src/core/lib/iomgr/socket_mutator.h
  50. 5
      src/core/lib/iomgr/timer.h
  51. 2
      src/core/lib/security/credentials/jwt/json_token.h
  52. 2
      src/core/lib/security/credentials/jwt/jwt_verifier.cc
  53. 2
      src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
  54. 2
      src/core/lib/surface/call.cc
  55. 1
      src/core/lib/surface/init.h
  56. 4
      src/core/lib/transport/service_config.cc
  57. 6
      src/core/lib/transport/service_config.h
  58. 2
      src/core/tsi/alts/crypt/aes_gcm.cc
  59. 3006
      src/core/tsi/grpc_shadow_boringssl.h
  60. 2
      src/core/tsi/ssl/session_cache/ssl_session.h
  61. 2
      src/core/tsi/ssl/session_cache/ssl_session_cache.h
  62. 4
      src/core/tsi/ssl_transport_security.cc
  63. 2
      src/core/tsi/ssl_types.h
  64. 4
      src/cpp/ext/filters/census/grpc_plugin.h
  65. 2
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  66. 2
      src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
  67. 4
      src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
  68. 2
      src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs
  69. 4527
      src/objective-c/BoringSSL-GRPC.podspec
  70. 1539
      src/objective-c/BoringSSL.podspec
  71. 22
      src/objective-c/README.md
  72. 2
      src/objective-c/examples/Sample/Podfile
  73. 2
      src/objective-c/examples/SwiftSample/Podfile
  74. 2974
      src/objective-c/grpc_shadow_boringssl_symbol_list
  75. 2
      src/objective-c/tests/Connectivity/Podfile
  76. 4
      src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
  77. 6
      src/objective-c/tests/Podfile
  78. 8
      src/objective-c/tests/Tests.xcodeproj/project.pbxproj
  79. 16
      src/php/tests/unit_tests/PersistentChannelTests/PersistentChannelTest.php
  80. 11
      src/python/grpcio/commands.py
  81. 59
      src/python/grpcio/grpc/_channel.py
  82. 2
      src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
  83. 1
      src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi
  84. 63
      src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
  85. 2
      src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
  86. 46
      src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
  87. 29
      src/python/grpcio/grpc/_cython/_cygrpc/fork_posix.pxd.pxi
  88. 207
      src/python/grpcio/grpc/_cython/_cygrpc/fork_posix.pyx.pxi
  89. 63
      src/python/grpcio/grpc/_cython/_cygrpc/fork_windows.pyx.pxi
  90. 1
      src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
  91. 2
      src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
  92. 39
      src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
  93. 3
      src/python/grpcio/grpc/_cython/cygrpc.pxd
  94. 5
      src/python/grpcio/grpc/_cython/cygrpc.pyx
  95. 25
      src/python/grpcio_tests/commands.py
  96. 1
      src/python/grpcio_tests/setup.py
  97. 13
      src/python/grpcio_tests/tests/fork/__init__.py
  98. 76
      src/python/grpcio_tests/tests/fork/client.py
  99. 445
      src/python/grpcio_tests/tests/fork/methods.py
  100. 2
      src/python/grpcio_tests/tests/stress/test_runner.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -20,6 +20,8 @@ notes=FIXME,XXX
[MESSAGES CONTROL]
extension-pkg-whitelist=grpc._cython.cygrpc
disable=
# These suppressions are specific to tests:
#

10
BUILD

@ -1549,6 +1549,7 @@ grpc_cc_library(
"grpc_base",
"grpc_transport_chttp2_alpn",
"tsi",
"grpc_shadow_boringssl",
],
)
@ -1809,6 +1810,7 @@ grpc_cc_library(
"gpr",
"grpc_base",
"tsi_interface",
"grpc_shadow_boringssl",
],
)
@ -1905,6 +1907,7 @@ grpc_cc_library(
"grpc_base",
"grpc_transport_chttp2_client_insecure",
"tsi_interface",
"grpc_shadow_boringssl",
],
)
@ -2160,4 +2163,11 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "grpc_shadow_boringssl",
hdrs = [
"src/core/tsi/grpc_shadow_boringssl.h",
],
)
grpc_generate_one_off_targets()

@ -103,6 +103,9 @@ repository at the latest stable version.
In the C++ world, there's no "standard" build system that would work for in all supported use cases and on all supported platforms.
Therefore, gRPC supports several major build systems, which should satisfy most users.
Note that this section only covers the build of gRPC itself, not the installation. See the [How to use](https://github.com/grpc/grpc/tree/master/src/cpp#to-start-using-grpc-c) instructions
for guidance on how to add gRPC as a dependency to a C++ application (there are several ways and system wide installation is often not the best choice).
## make (on UNIX systems)
From the grpc repository root

@ -69,6 +69,7 @@ filegroups:
- grpc_transport_chttp2_client_insecure
- tsi_interface
- tsi
- grpc_shadow_boringssl
- name: alts_util
public_headers:
- include/grpc/grpc_security.h
@ -841,6 +842,7 @@ filegroups:
- grpc_base
- grpc_transport_chttp2_alpn
- tsi
- grpc_shadow_boringssl
- name: grpc_server_backward_compatibility
headers:
- src/core/ext/filters/workarounds/workaround_utils.h
@ -848,6 +850,9 @@ filegroups:
- src/core/ext/filters/workarounds/workaround_utils.cc
uses:
- grpc_base
- name: grpc_shadow_boringssl
headers:
- src/core/tsi/grpc_shadow_boringssl.h
- name: grpc_test_util_base
build: test
headers:
@ -1109,6 +1114,7 @@ filegroups:
- tsi_interface
- grpc_base
- grpc_trace
- grpc_shadow_boringssl
- name: tsi_interface
headers:
- src/core/tsi/transport_security.h

@ -17,7 +17,14 @@ if("${gRPC_SSL_PROVIDER}" STREQUAL "module")
set(BORINGSSL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/boringssl)
endif()
if(EXISTS "${BORINGSSL_ROOT_DIR}/CMakeLists.txt")
set(OPENSSL_NO_ASM ON) # make boringssl buildable with Visual Studio
if (MSVC AND NOT CMAKE_GENERATOR STREQUAL "Ninja")
# Visual Studio build with assembly optimizations is broken,
# but it works with Ninja generator.
# This will get eventually fixed in cmake, but until then
# we need to disable assembly optimizations.
# See https://github.com/grpc/grpc/issues/16376
set(OPENSSL_NO_ASM ON)
endif()
add_subdirectory(${BORINGSSL_ROOT_DIR} third_party/boringssl)
if(TARGET ssl)
set(_gRPC_SSL_LIBRARIES ssl)

@ -56,7 +56,7 @@ For example, in the following code block, error1 and error2 are owned by the
current function.
```C
grpc_error* error1 = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occured");
grpc_error* error1 = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred");
grpc_error* error2 = some_operation_that_might_fail(...);
```
@ -87,7 +87,7 @@ callbacks with `GRPC_CLOSURE_RUN` and `GRPC_CLOSURE_SCHED`. These functions are
not callbacks, so they will take ownership of the error passed to them.
```C
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occured");
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred");
GRPC_CLOSURE_RUN(exec_ctx, cb, error);
// current function no longer has ownership of the error
```
@ -96,7 +96,7 @@ If you schedule or run a closure, but still need ownership of the error, then
you must explicitly take a reference.
```C
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occured");
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred");
GRPC_CLOSURE_RUN(exec_ctx, cb, GRPC_ERROR_REF(error));
// do some other things with the error
GRPC_ERROR_UNREF(error);
@ -128,7 +128,7 @@ void on_some_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
Take the following example:
```C
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occured");
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred");
// do some things
some_function(error);
// can't use error anymore! might be gone.

@ -17,3 +17,6 @@ number:
`include/grpc++/impl/codegen/client_context.h` (commit `9477724`)
- remove directory `include/grpc++` and all headers in it
(commit `eb06572`)
- make all `Request` and `Mark` methods in `grpc::Service` take a
`size_t` argument for `index` rather than `int` (since that is only
used as a vector index)

@ -14,7 +14,9 @@ Makefile | all other cases | all | :x:
Bazel | | Linux | :heavy_check_mark:
Bazel | | MacOS | :heavy_check_mark:
Bazel | | Windows | :x:
CMake | boringssl from submodule (default) | all | :x:
CMake | boringssl from submodule (default) | Linux or MacOS | :heavy_check_mark:
CMake | boringssl from submodule (default), generator=Ninja | Windows | :heavy_check_mark:
CMake | boringssl from submodule (default), generator=Visual Studio | Windows | :x:
CMake | pre-installed OpenSSL 1.0.2+ (`gRPC_SSL_PROVIDER=package`) | all | :heavy_check_mark:
## Other Languages: Binary/Source Packages

@ -9,10 +9,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.5.0" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.5.0" />
<PackageReference Include="Grpc" Version="1.13.1" />
<PackageReference Include="Grpc.Tools" Version="1.13.1" />
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.6.1" />
<PackageReference Include="Grpc" Version="1.14.1" />
<PackageReference Include="Grpc.Tools" Version="1.14.1" />
</ItemGroup>
</Project>

@ -1,5 +1,7 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@ -44,6 +46,7 @@ namespace Helloworld {
/// </summary>
public sealed partial class HelloRequest : pb::IMessage<HelloRequest> {
private static readonly pb::MessageParser<HelloRequest> _parser = new pb::MessageParser<HelloRequest>(() => new HelloRequest());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HelloRequest> Parser { get { return _parser; } }
@ -67,6 +70,7 @@ namespace Helloworld {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloRequest(HelloRequest other) : this() {
name_ = other.name_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -99,13 +103,16 @@ namespace Helloworld {
return true;
}
if (Name != other.Name) return false;
return true;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
@ -120,6 +127,9 @@ namespace Helloworld {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -128,6 +138,9 @@ namespace Helloworld {
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
@ -139,6 +152,7 @@ namespace Helloworld {
if (other.Name.Length != 0) {
Name = other.Name;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -147,7 +161,7 @@ namespace Helloworld {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
@ -164,6 +178,7 @@ namespace Helloworld {
/// </summary>
public sealed partial class HelloReply : pb::IMessage<HelloReply> {
private static readonly pb::MessageParser<HelloReply> _parser = new pb::MessageParser<HelloReply>(() => new HelloReply());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HelloReply> Parser { get { return _parser; } }
@ -187,6 +202,7 @@ namespace Helloworld {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloReply(HelloReply other) : this() {
message_ = other.message_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -219,13 +235,16 @@ namespace Helloworld {
return true;
}
if (Message != other.Message) return false;
return true;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Message.Length != 0) hash ^= Message.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
@ -240,6 +259,9 @@ namespace Helloworld {
output.WriteRawTag(10);
output.WriteString(Message);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -248,6 +270,9 @@ namespace Helloworld {
if (Message.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
@ -259,6 +284,7 @@ namespace Helloworld {
if (other.Message.Length != 0) {
Message = other.Message;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -267,7 +293,7 @@ namespace Helloworld {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Message = input.ReadString();

@ -1,5 +1,7 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
// </auto-generated>
// Original file comments:
// Copyright 2015 gRPC authors.
//
@ -15,12 +17,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma warning disable 1591
#pragma warning disable 0414, 1591
#region Designer generated code
using System;
using System.Threading;
using System.Threading.Tasks;
using grpc = global::Grpc.Core;
namespace Helloworld {
@ -31,15 +30,15 @@ namespace Helloworld {
{
static readonly string __ServiceName = "helloworld.Greeter";
static readonly grpc::Marshaller<global::Helloworld.HelloRequest> __Marshaller_HelloRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Helloworld.HelloReply> __Marshaller_HelloReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Helloworld.HelloRequest> __Marshaller_helloworld_HelloRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Helloworld.HelloReply> __Marshaller_helloworld_HelloReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom);
static readonly grpc::Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply> __Method_SayHello = new grpc::Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply>(
grpc::MethodType.Unary,
__ServiceName,
"SayHello",
__Marshaller_HelloRequest,
__Marshaller_HelloReply);
__Marshaller_helloworld_HelloRequest,
__Marshaller_helloworld_HelloReply);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
@ -94,7 +93,7 @@ namespace Helloworld {
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The response received from the server.</returns>
public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return SayHello(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
@ -116,7 +115,7 @@ namespace Helloworld {
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual grpc::AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return SayHelloAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}

@ -19,8 +19,9 @@ setlocal
@rem enter this directory
cd /d %~dp0
set PROTOC=%UserProfile%\.nuget\packages\Google.Protobuf.Tools\3.5.0\tools\windows_x64\protoc.exe
set PLUGIN=%UserProfile%\.nuget\packages\Grpc.Tools\1.8.0\tools\windows_x64\grpc_csharp_plugin.exe
@rem packages will be available in nuget cache directory once the project is built or after "dotnet restore"
set PROTOC=%UserProfile%\.nuget\packages\Google.Protobuf.Tools\3.6.1\tools\windows_x64\protoc.exe
set PLUGIN=%UserProfile%\.nuget\packages\Grpc.Tools\1.14.1\tools\windows_x64\grpc_csharp_plugin.exe
%PROTOC% -I../../protos --csharp_out Greeter ../../protos/helloworld.proto --grpc_out Greeter --plugin=protoc-gen-grpc=%PLUGIN%

@ -32,18 +32,17 @@
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="Google.Protobuf, Version=3.5.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.5.0\lib\net45\Google.Protobuf.dll</HintPath>
<Private>True</Private>
<Reference Include="Google.Protobuf, Version=3.6.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.6.1\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<HintPath>..\packages\Grpc.Core.1.14.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Interactive.Async, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Grpc.Core">
<HintPath>..\packages\Grpc.Core.1.13.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
@ -62,5 +61,11 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="..\packages\Grpc.Core.1.13.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.13.1\build\net45\Grpc.Core.targets')" />
<Import Project="..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets'))" />
</Target>
</Project>

@ -1,5 +1,7 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@ -44,6 +46,7 @@ namespace Helloworld {
/// </summary>
public sealed partial class HelloRequest : pb::IMessage<HelloRequest> {
private static readonly pb::MessageParser<HelloRequest> _parser = new pb::MessageParser<HelloRequest>(() => new HelloRequest());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HelloRequest> Parser { get { return _parser; } }
@ -67,6 +70,7 @@ namespace Helloworld {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloRequest(HelloRequest other) : this() {
name_ = other.name_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -99,13 +103,16 @@ namespace Helloworld {
return true;
}
if (Name != other.Name) return false;
return true;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
@ -120,6 +127,9 @@ namespace Helloworld {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -128,6 +138,9 @@ namespace Helloworld {
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
@ -139,6 +152,7 @@ namespace Helloworld {
if (other.Name.Length != 0) {
Name = other.Name;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -147,7 +161,7 @@ namespace Helloworld {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
@ -164,6 +178,7 @@ namespace Helloworld {
/// </summary>
public sealed partial class HelloReply : pb::IMessage<HelloReply> {
private static readonly pb::MessageParser<HelloReply> _parser = new pb::MessageParser<HelloReply>(() => new HelloReply());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HelloReply> Parser { get { return _parser; } }
@ -187,6 +202,7 @@ namespace Helloworld {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloReply(HelloReply other) : this() {
message_ = other.message_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -219,13 +235,16 @@ namespace Helloworld {
return true;
}
if (Message != other.Message) return false;
return true;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Message.Length != 0) hash ^= Message.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
@ -240,6 +259,9 @@ namespace Helloworld {
output.WriteRawTag(10);
output.WriteString(Message);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -248,6 +270,9 @@ namespace Helloworld {
if (Message.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
@ -259,6 +284,7 @@ namespace Helloworld {
if (other.Message.Length != 0) {
Message = other.Message;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -267,7 +293,7 @@ namespace Helloworld {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Message = input.ReadString();

@ -1,5 +1,7 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
// </auto-generated>
// Original file comments:
// Copyright 2015 gRPC authors.
//
@ -15,12 +17,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma warning disable 1591
#pragma warning disable 0414, 1591
#region Designer generated code
using System;
using System.Threading;
using System.Threading.Tasks;
using grpc = global::Grpc.Core;
namespace Helloworld {
@ -31,15 +30,15 @@ namespace Helloworld {
{
static readonly string __ServiceName = "helloworld.Greeter";
static readonly grpc::Marshaller<global::Helloworld.HelloRequest> __Marshaller_HelloRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Helloworld.HelloReply> __Marshaller_HelloReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Helloworld.HelloRequest> __Marshaller_helloworld_HelloRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Helloworld.HelloReply> __Marshaller_helloworld_HelloReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom);
static readonly grpc::Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply> __Method_SayHello = new grpc::Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply>(
grpc::MethodType.Unary,
__ServiceName,
"SayHello",
__Marshaller_HelloRequest,
__Marshaller_HelloReply);
__Marshaller_helloworld_HelloRequest,
__Marshaller_helloworld_HelloReply);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
@ -94,7 +93,7 @@ namespace Helloworld {
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The response received from the server.</returns>
public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return SayHello(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
@ -116,7 +115,7 @@ namespace Helloworld {
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual grpc::AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return SayHelloAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.5.0" targetFramework="net45" />
<package id="Grpc" version="1.13.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.13.1" targetFramework="net45" />
<package id="Grpc.Tools" version="1.13.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.6.1" targetFramework="net45" />
<package id="Grpc" version="1.14.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.14.1" targetFramework="net45" />
<package id="Grpc.Tools" version="1.14.1" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages>

@ -32,18 +32,17 @@
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="Google.Protobuf, Version=3.5.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.5.0\lib\net45\Google.Protobuf.dll</HintPath>
<Private>True</Private>
<Reference Include="Google.Protobuf, Version=3.6.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.6.1\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<HintPath>..\packages\Grpc.Core.1.14.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Interactive.Async, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Grpc.Core">
<HintPath>..\packages\Grpc.Core.1.13.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
@ -60,5 +59,11 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="..\packages\Grpc.Core.1.13.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.13.1\build\net45\Grpc.Core.targets')" />
<Import Project="..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets'))" />
</Target>
</Project>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.5.0" targetFramework="net45" />
<package id="Grpc" version="1.13.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.13.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.6.1" targetFramework="net45" />
<package id="Grpc" version="1.14.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.14.1" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages>

@ -32,18 +32,17 @@
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="Google.Protobuf, Version=3.5.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.5.0\lib\net45\Google.Protobuf.dll</HintPath>
<Private>True</Private>
<Reference Include="Google.Protobuf, Version=3.6.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.6.1\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<HintPath>..\packages\Grpc.Core.1.14.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Interactive.Async, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Grpc.Core">
<HintPath>..\packages\Grpc.Core.1.13.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
@ -60,5 +59,11 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="..\packages\Grpc.Core.1.13.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.13.1\build\net45\Grpc.Core.targets')" />
<Import Project="..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.14.1\build\net45\Grpc.Core.targets'))" />
</Target>
</Project>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.5.0" targetFramework="net45" />
<package id="Grpc" version="1.13.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.13.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.6.1" targetFramework="net45" />
<package id="Grpc" version="1.14.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.14.1" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages>

@ -19,7 +19,7 @@ setlocal
@rem enter this directory
cd /d %~dp0
set TOOLS_PATH=packages\Grpc.Tools.1.8.0\tools\windows_x86
set TOOLS_PATH=packages\Grpc.Tools.1.14.1\tools\windows_x86
%TOOLS_PATH%\protoc.exe -I../../protos --csharp_out Greeter ../../protos/helloworld.proto --grpc_out Greeter --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe

@ -1,5 +1,7 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: route_guide.proto
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: route_guide.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
@ -60,6 +62,7 @@ namespace Routeguide {
/// </summary>
public sealed partial class Point : pb::IMessage<Point> {
private static readonly pb::MessageParser<Point> _parser = new pb::MessageParser<Point>(() => new Point());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Point> Parser { get { return _parser; } }
@ -84,6 +87,7 @@ namespace Routeguide {
public Point(Point other) : this() {
latitude_ = other.latitude_;
longitude_ = other.longitude_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -128,7 +132,7 @@ namespace Routeguide {
}
if (Latitude != other.Latitude) return false;
if (Longitude != other.Longitude) return false;
return true;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -136,6 +140,9 @@ namespace Routeguide {
int hash = 1;
if (Latitude != 0) hash ^= Latitude.GetHashCode();
if (Longitude != 0) hash ^= Longitude.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
@ -154,6 +161,9 @@ namespace Routeguide {
output.WriteRawTag(16);
output.WriteInt32(Longitude);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -165,6 +175,9 @@ namespace Routeguide {
if (Longitude != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Longitude);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
@ -179,6 +192,7 @@ namespace Routeguide {
if (other.Longitude != 0) {
Longitude = other.Longitude;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -187,7 +201,7 @@ namespace Routeguide {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Latitude = input.ReadInt32();
@ -209,6 +223,7 @@ namespace Routeguide {
/// </summary>
public sealed partial class Rectangle : pb::IMessage<Rectangle> {
private static readonly pb::MessageParser<Rectangle> _parser = new pb::MessageParser<Rectangle>(() => new Rectangle());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Rectangle> Parser { get { return _parser; } }
@ -231,8 +246,9 @@ namespace Routeguide {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Rectangle(Rectangle other) : this() {
Lo = other.lo_ != null ? other.Lo.Clone() : null;
Hi = other.hi_ != null ? other.Hi.Clone() : null;
lo_ = other.lo_ != null ? other.lo_.Clone() : null;
hi_ = other.hi_ != null ? other.hi_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -283,7 +299,7 @@ namespace Routeguide {
}
if (!object.Equals(Lo, other.Lo)) return false;
if (!object.Equals(Hi, other.Hi)) return false;
return true;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -291,6 +307,9 @@ namespace Routeguide {
int hash = 1;
if (lo_ != null) hash ^= Lo.GetHashCode();
if (hi_ != null) hash ^= Hi.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
@ -309,6 +328,9 @@ namespace Routeguide {
output.WriteRawTag(18);
output.WriteMessage(Hi);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -320,6 +342,9 @@ namespace Routeguide {
if (hi_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Hi);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
@ -340,6 +365,7 @@ namespace Routeguide {
}
Hi.MergeFrom(other.Hi);
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -348,7 +374,7 @@ namespace Routeguide {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (lo_ == null) {
@ -377,6 +403,7 @@ namespace Routeguide {
/// </summary>
public sealed partial class Feature : pb::IMessage<Feature> {
private static readonly pb::MessageParser<Feature> _parser = new pb::MessageParser<Feature>(() => new Feature());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Feature> Parser { get { return _parser; } }
@ -400,7 +427,8 @@ namespace Routeguide {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Feature(Feature other) : this() {
name_ = other.name_;
Location = other.location_ != null ? other.Location.Clone() : null;
location_ = other.location_ != null ? other.location_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -451,7 +479,7 @@ namespace Routeguide {
}
if (Name != other.Name) return false;
if (!object.Equals(Location, other.Location)) return false;
return true;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -459,6 +487,9 @@ namespace Routeguide {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (location_ != null) hash ^= Location.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
@ -477,6 +508,9 @@ namespace Routeguide {
output.WriteRawTag(18);
output.WriteMessage(Location);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -488,6 +522,9 @@ namespace Routeguide {
if (location_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Location);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
@ -505,6 +542,7 @@ namespace Routeguide {
}
Location.MergeFrom(other.Location);
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -513,7 +551,7 @@ namespace Routeguide {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
@ -537,6 +575,7 @@ namespace Routeguide {
/// </summary>
public sealed partial class RouteNote : pb::IMessage<RouteNote> {
private static readonly pb::MessageParser<RouteNote> _parser = new pb::MessageParser<RouteNote>(() => new RouteNote());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<RouteNote> Parser { get { return _parser; } }
@ -559,8 +598,9 @@ namespace Routeguide {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteNote(RouteNote other) : this() {
Location = other.location_ != null ? other.Location.Clone() : null;
location_ = other.location_ != null ? other.location_.Clone() : null;
message_ = other.message_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -611,7 +651,7 @@ namespace Routeguide {
}
if (!object.Equals(Location, other.Location)) return false;
if (Message != other.Message) return false;
return true;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -619,6 +659,9 @@ namespace Routeguide {
int hash = 1;
if (location_ != null) hash ^= Location.GetHashCode();
if (Message.Length != 0) hash ^= Message.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
@ -637,6 +680,9 @@ namespace Routeguide {
output.WriteRawTag(18);
output.WriteString(Message);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -648,6 +694,9 @@ namespace Routeguide {
if (Message.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
@ -665,6 +714,7 @@ namespace Routeguide {
if (other.Message.Length != 0) {
Message = other.Message;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -673,7 +723,7 @@ namespace Routeguide {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (location_ == null) {
@ -701,6 +751,7 @@ namespace Routeguide {
/// </summary>
public sealed partial class RouteSummary : pb::IMessage<RouteSummary> {
private static readonly pb::MessageParser<RouteSummary> _parser = new pb::MessageParser<RouteSummary>(() => new RouteSummary());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<RouteSummary> Parser { get { return _parser; } }
@ -727,6 +778,7 @@ namespace Routeguide {
featureCount_ = other.featureCount_;
distance_ = other.distance_;
elapsedTime_ = other.elapsedTime_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -807,7 +859,7 @@ namespace Routeguide {
if (FeatureCount != other.FeatureCount) return false;
if (Distance != other.Distance) return false;
if (ElapsedTime != other.ElapsedTime) return false;
return true;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -817,6 +869,9 @@ namespace Routeguide {
if (FeatureCount != 0) hash ^= FeatureCount.GetHashCode();
if (Distance != 0) hash ^= Distance.GetHashCode();
if (ElapsedTime != 0) hash ^= ElapsedTime.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
@ -843,6 +898,9 @@ namespace Routeguide {
output.WriteRawTag(32);
output.WriteInt32(ElapsedTime);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -860,6 +918,9 @@ namespace Routeguide {
if (ElapsedTime != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ElapsedTime);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
@ -880,6 +941,7 @@ namespace Routeguide {
if (other.ElapsedTime != 0) {
ElapsedTime = other.ElapsedTime;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -888,7 +950,7 @@ namespace Routeguide {
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
PointCount = input.ReadInt32();

@ -9,10 +9,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.5.0" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.5.0" />
<PackageReference Include="Grpc" Version="1.13.1" />
<PackageReference Include="Grpc.Tools" Version="1.13.1" />
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.6.1" />
<PackageReference Include="Grpc" Version="1.14.1" />
<PackageReference Include="Grpc.Tools" Version="1.14.1" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
</ItemGroup>

@ -1,5 +1,7 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: route_guide.proto
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: route_guide.proto
// </auto-generated>
// Original file comments:
// Copyright 2015 gRPC authors.
//
@ -15,12 +17,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#pragma warning disable 1591
#pragma warning disable 0414, 1591
#region Designer generated code
using System;
using System.Threading;
using System.Threading.Tasks;
using grpc = global::Grpc.Core;
namespace Routeguide {
@ -31,39 +30,39 @@ namespace Routeguide {
{
static readonly string __ServiceName = "routeguide.RouteGuide";
static readonly grpc::Marshaller<global::Routeguide.Point> __Marshaller_Point = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Point.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.Feature> __Marshaller_Feature = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Feature.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.Rectangle> __Marshaller_Rectangle = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Rectangle.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.RouteSummary> __Marshaller_RouteSummary = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.RouteSummary.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.RouteNote> __Marshaller_RouteNote = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.RouteNote.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.Point> __Marshaller_routeguide_Point = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Point.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.Feature> __Marshaller_routeguide_Feature = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Feature.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.Rectangle> __Marshaller_routeguide_Rectangle = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.Rectangle.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.RouteSummary> __Marshaller_routeguide_RouteSummary = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.RouteSummary.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Routeguide.RouteNote> __Marshaller_routeguide_RouteNote = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Routeguide.RouteNote.Parser.ParseFrom);
static readonly grpc::Method<global::Routeguide.Point, global::Routeguide.Feature> __Method_GetFeature = new grpc::Method<global::Routeguide.Point, global::Routeguide.Feature>(
grpc::MethodType.Unary,
__ServiceName,
"GetFeature",
__Marshaller_Point,
__Marshaller_Feature);
__Marshaller_routeguide_Point,
__Marshaller_routeguide_Feature);
static readonly grpc::Method<global::Routeguide.Rectangle, global::Routeguide.Feature> __Method_ListFeatures = new grpc::Method<global::Routeguide.Rectangle, global::Routeguide.Feature>(
grpc::MethodType.ServerStreaming,
__ServiceName,
"ListFeatures",
__Marshaller_Rectangle,
__Marshaller_Feature);
__Marshaller_routeguide_Rectangle,
__Marshaller_routeguide_Feature);
static readonly grpc::Method<global::Routeguide.Point, global::Routeguide.RouteSummary> __Method_RecordRoute = new grpc::Method<global::Routeguide.Point, global::Routeguide.RouteSummary>(
grpc::MethodType.ClientStreaming,
__ServiceName,
"RecordRoute",
__Marshaller_Point,
__Marshaller_RouteSummary);
__Marshaller_routeguide_Point,
__Marshaller_routeguide_RouteSummary);
static readonly grpc::Method<global::Routeguide.RouteNote, global::Routeguide.RouteNote> __Method_RouteChat = new grpc::Method<global::Routeguide.RouteNote, global::Routeguide.RouteNote>(
grpc::MethodType.DuplexStreaming,
__ServiceName,
"RouteChat",
__Marshaller_RouteNote,
__Marshaller_RouteNote);
__Marshaller_routeguide_RouteNote,
__Marshaller_routeguide_RouteNote);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
@ -174,7 +173,7 @@ namespace Routeguide {
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The response received from the server.</returns>
public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return GetFeature(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
@ -206,7 +205,7 @@ namespace Routeguide {
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual grpc::AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return GetFeatureAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
@ -238,7 +237,7 @@ namespace Routeguide {
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual grpc::AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return ListFeatures(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
@ -267,7 +266,7 @@ namespace Routeguide {
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual grpc::AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return RecordRoute(new grpc::CallOptions(headers, deadline, cancellationToken));
}
@ -293,7 +292,7 @@ namespace Routeguide {
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual grpc::AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
{
return RouteChat(new grpc::CallOptions(headers, deadline, cancellationToken));
}

@ -19,8 +19,10 @@ setlocal
@rem enter this directory
cd /d %~dp0
set TOOLS_PATH=packages\Grpc.Tools.1.8.0\tools\windows_x86
@rem packages will be available in nuget cache directory once the project is built or after "dotnet restore"
set PROTOC=%UserProfile%\.nuget\packages\Google.Protobuf.Tools\3.6.1\tools\windows_x64\protoc.exe
set PLUGIN=%UserProfile%\.nuget\packages\Grpc.Tools\1.14.1\tools\windows_x64\grpc_csharp_plugin.exe
%TOOLS_PATH%\protoc.exe -I../../protos --csharp_out RouteGuide ../../protos/route_guide.proto --grpc_out RouteGuide --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe
%PROTOC% -I../../protos --csharp_out RouteGuide ../../protos/route_guide.proto --grpc_out RouteGuide --plugin=protoc-gen-grpc=%PLUGIN%
endlocal

@ -348,6 +348,7 @@ Pod::Spec.new do |s|
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security_grpc.h',
'src/core/tsi/grpc_shadow_boringssl.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/transport/inproc/inproc_transport.h',
'src/core/lib/avl/avl.h',

@ -181,8 +181,9 @@ Pod::Spec.new do |s|
ss.header_mappings_dir = '.'
ss.libraries = 'z'
ss.dependency "#{s.name}/Interface", version
ss.dependency 'BoringSSL', '~> 10.0'
ss.dependency 'BoringSSL-GRPC', '0.0.1'
ss.dependency 'nanopb', '~> 0.3'
ss.compiler_flags = '-DGRPC_SHADOW_BORINGSSL_SYMBOLS'
# To save you from scrolling, this is the last part of the podspec.
ss.source_files = 'src/core/lib/gpr/alloc.h',
@ -359,6 +360,7 @@ Pod::Spec.new do |s|
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security_grpc.h',
'src/core/tsi/grpc_shadow_boringssl.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/transport/inproc/inproc_transport.h',
'src/core/lib/avl/avl.h',
@ -957,6 +959,7 @@ Pod::Spec.new do |s|
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security_grpc.h',
'src/core/tsi/grpc_shadow_boringssl.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/transport/inproc/inproc_transport.h',
'src/core/lib/avl/avl.h',

@ -15,6 +15,7 @@ EXPORTS
grpc_register_plugin
grpc_init
grpc_shutdown
grpc_is_initialized
grpc_version_string
grpc_g_stands_for
grpc_completion_queue_factory_lookup

@ -296,6 +296,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/tsi/ssl_transport_security.h )
s.files += %w( src/core/tsi/ssl_types.h )
s.files += %w( src/core/tsi/transport_security_grpc.h )
s.files += %w( src/core/tsi/grpc_shadow_boringssl.h )
s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.h )
s.files += %w( src/core/ext/transport/inproc/inproc_transport.h )
s.files += %w( src/core/lib/avl/avl.h )

@ -79,6 +79,12 @@ GRPCAPI void grpc_init(void);
destroyed. */
GRPCAPI void grpc_shutdown(void);
/** EXPERIMENTAL. Returns 1 if the grpc library has been initialized.
TODO(ericgribkoff) Decide if this should be promoted to non-experimental as
part of stabilizing the fork support API, as tracked in
https://github.com/grpc/grpc/issues/15334 */
GRPCAPI int grpc_is_initialized(void);
/** Return a string representing the current version of grpc */
GRPCAPI const char* grpc_version_string(void);

@ -282,6 +282,47 @@
#else /* _LP64 */
#define GPR_ARCH_32 1
#endif /* _LP64 */
#elif defined(__sun) && defined(__SVR4)
#define GPR_PLATFORM_STRING "solaris"
#define GPR_SOLARIS 1
#define GPR_CPU_POSIX 1
#define GPR_GCC_ATOMIC 1
#define GPR_GCC_TLS 1
#define GPR_POSIX_LOG 1
#define GPR_POSIX_ENV 1
#define GPR_POSIX_TMPFILE 1
#define GPR_POSIX_STRING 1
#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
#ifdef _LP64
#define GPR_ARCH_64 1
#else /* _LP64 */
#define GPR_ARCH_32 1
#endif /* _LP64 */
#elif defined(_AIX)
#define GPR_PLATFORM_STRING "aix"
#ifndef _ALL_SOURCE
#define _ALL_SOURCE
#endif
#define GPR_AIX 1
#define GPR_CPU_POSIX 1
#define GPR_GCC_ATOMIC 1
#define GPR_GCC_TLS 1
#define GPR_POSIX_LOG 1
#define GPR_POSIX_ENV 1
#define GPR_POSIX_TMPFILE 1
#define GPR_POSIX_STRING 1
#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
#ifdef _LP64
#define GPR_ARCH_64 1
#else /* _LP64 */
#define GPR_ARCH_32 1
#endif /* _LP64 */
#elif defined(__native_client__)
#define GPR_PLATFORM_STRING "nacl"
#ifndef _BSD_SOURCE

@ -93,14 +93,19 @@ class Service {
internal::ServerAsyncStreamingInterface* stream,
CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag) {
server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
// Typecast the index to size_t for indexing into a vector
// while preserving the API that existed before a compiler
// warning was first seen (grpc/grpc#11664)
size_t idx = static_cast<size_t>(index);
server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
notification_cq, tag, request);
}
void RequestAsyncClientStreaming(
int index, ServerContext* context,
internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag) {
server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
size_t idx = static_cast<size_t>(index);
server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
notification_cq, tag);
}
template <class Message>
@ -108,14 +113,16 @@ class Service {
int index, ServerContext* context, Message* request,
internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag) {
server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
size_t idx = static_cast<size_t>(index);
server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
notification_cq, tag, request);
}
void RequestAsyncBidiStreaming(
int index, ServerContext* context,
internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag) {
server_->RequestAsyncCall(methods_[index].get(), context, stream, call_cq,
size_t idx = static_cast<size_t>(index);
server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
notification_cq, tag);
}
@ -126,46 +133,50 @@ class Service {
void MarkMethodAsync(int index) {
// This does not have to be a hard error, however no one has approached us
// with a use case yet. Please file an issue if you believe you have one.
size_t idx = static_cast<size_t>(index);
GPR_CODEGEN_ASSERT(
methods_[index].get() != nullptr &&
methods_[idx].get() != nullptr &&
"Cannot mark the method as 'async' because it has already been "
"marked as 'generic'.");
methods_[index]->SetServerAsyncType(
methods_[idx]->SetServerAsyncType(
internal::RpcServiceMethod::AsyncType::ASYNC);
}
void MarkMethodRaw(int index) {
// This does not have to be a hard error, however no one has approached us
// with a use case yet. Please file an issue if you believe you have one.
GPR_CODEGEN_ASSERT(methods_[index].get() != nullptr &&
size_t idx = static_cast<size_t>(index);
GPR_CODEGEN_ASSERT(methods_[idx].get() != nullptr &&
"Cannot mark the method as 'raw' because it has already "
"been marked as 'generic'.");
methods_[index]->SetServerAsyncType(
methods_[idx]->SetServerAsyncType(
internal::RpcServiceMethod::AsyncType::RAW);
}
void MarkMethodGeneric(int index) {
// This does not have to be a hard error, however no one has approached us
// with a use case yet. Please file an issue if you believe you have one.
size_t idx = static_cast<size_t>(index);
GPR_CODEGEN_ASSERT(
methods_[index]->handler() != nullptr &&
methods_[idx]->handler() != nullptr &&
"Cannot mark the method as 'generic' because it has already been "
"marked as 'async' or 'raw'.");
methods_[index].reset();
methods_[idx].reset();
}
void MarkMethodStreamed(int index, internal::MethodHandler* streamed_method) {
// This does not have to be a hard error, however no one has approached us
// with a use case yet. Please file an issue if you believe you have one.
GPR_CODEGEN_ASSERT(methods_[index] && methods_[index]->handler() &&
size_t idx = static_cast<size_t>(index);
GPR_CODEGEN_ASSERT(methods_[idx] && methods_[idx]->handler() &&
"Cannot mark an async or generic method Streamed");
methods_[index]->SetHandler(streamed_method);
methods_[idx]->SetHandler(streamed_method);
// From the server's point of view, streamed unary is a special
// case of BIDI_STREAMING that has 1 read and 1 write, in that order,
// and split server-side streaming is BIDI_STREAMING with 1 read and
// any number of writes, in that order.
methods_[index]->SetMethodType(internal::RpcMethod::BIDI_STREAMING);
methods_[idx]->SetMethodType(internal::RpcMethod::BIDI_STREAMING);
}
private:

@ -19,6 +19,12 @@
#ifndef GRPCPP_OPENCENSUS_H
#define GRPCPP_OPENCENSUS_H
#ifndef GRPC_BAZEL_BUILD
#error OpenCensus for gRPC is only supported when building with bazel.
#endif
#include "opencensus/trace/span.h"
namespace grpc {
// These symbols in this file will not be included in the binary unless
// grpc_opencensus_plugin build target was added as a dependency. At the moment
@ -36,6 +42,11 @@ void RegisterOpenCensusPlugin();
// ViewDescriptors below.
void RegisterOpenCensusViewsForExport();
class ServerContext;
// Returns the tracing Span for the current RPC.
::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context);
} // namespace grpc
#endif // GRPCPP_OPENCENSUS_H

@ -301,6 +301,7 @@
<file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_types.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security_grpc.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/grpc_shadow_boringssl.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/inproc/inproc_transport.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/avl/avl.h" role="src" />

@ -3101,7 +3101,7 @@ static void cc_start_transport_stream_op_batch(
// For all other batches, release the call combiner.
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: saved batch, yeilding call combiner", chand,
"chand=%p calld=%p: saved batch, yielding call combiner", chand,
calld);
}
GRPC_CALL_COMBINER_STOP(calld->call_combiner,

@ -139,7 +139,8 @@ class RoundRobin : public LoadBalancingPolicy {
grpc_client_channel_factory* client_channel_factory,
const grpc_channel_args& args)
: SubchannelList(policy, tracer, addresses, combiner,
client_channel_factory, args) {
client_channel_factory, args),
last_ready_index_(num_subchannels() - 1) {
// Need to maintain a ref to the LB policy as long as we maintain
// any references to subchannels, since the subchannels'
// pollset_sets will include the LB policy's pollset_set.
@ -180,7 +181,7 @@ class RoundRobin : public LoadBalancingPolicy {
size_t num_connecting_ = 0;
size_t num_transient_failure_ = 0;
grpc_error* last_transient_failure_error_ = GRPC_ERROR_NONE;
size_t last_ready_index_ = -1; // Index into list of last pick.
size_t last_ready_index_; // Index into list of last pick.
};
// Helper class to ensure that any function that modifies the child refs

@ -94,7 +94,7 @@ grpc_error* init_channel_elem(grpc_channel_element* elem,
if (default_authority_arg == nullptr) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"GRPC_ARG_DEFAULT_AUTHORITY channel arg. not found. Note that direct "
"channels must explicity specify a value for this argument.");
"channels must explicitly specify a value for this argument.");
}
const char* default_authority_str =
grpc_channel_arg_get_string(default_authority_arg);

@ -162,9 +162,10 @@ void ServerLoadReportingCallData::GetCensusSafeClientIpString(
} else if (addr->sa_family == GRPC_AF_INET6) {
grpc_sockaddr_in6* addr6 = reinterpret_cast<grpc_sockaddr_in6*>(addr);
*client_ip_string = static_cast<char*>(gpr_malloc(32 + 1));
for (size_t i = 0; i < 16; ++i) {
snprintf(*client_ip_string + i * 2, 2 + 1, "%02x",
addr6->sin6_addr.__in6_u.__u6_addr8[i]);
uint32_t* addr6_next_long = reinterpret_cast<uint32_t*>(&addr6->sin6_addr);
for (size_t i = 0; i < 4; ++i) {
snprintf(*client_ip_string + 8 * i, 8 + 1, "%08x",
grpc_ntohl(*addr6_next_long++));
}
*size = 32;
} else {

@ -77,16 +77,16 @@ void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
// would allow us to use the alignment actually needed by the caller.
typedef struct zone {
size_t size_begin; // All the space we have set aside for allocations up
// until this zone.
size_t size_end; // size_end = size_begin plus all the space we set aside for
// allocations in zone z itself.
zone* next;
} zone;
struct gpr_arena {
gpr_atm size_so_far;
// Keep track of the total used size. We use this in our call sizing
// historesis.
gpr_atm total_used;
size_t initial_zone_size;
zone initial_zone;
zone* last_zone;
gpr_mu arena_growth_mutex;
};
@ -100,14 +100,15 @@ gpr_arena* gpr_arena_create(size_t initial_size) {
initial_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_size);
gpr_arena* a = static_cast<gpr_arena*>(zalloc_aligned(
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + initial_size));
a->initial_zone.size_end = initial_size;
a->initial_zone_size = initial_size;
a->last_zone = &a->initial_zone;
gpr_mu_init(&a->arena_growth_mutex);
return a;
}
size_t gpr_arena_destroy(gpr_arena* arena) {
gpr_mu_destroy(&arena->arena_growth_mutex);
gpr_atm size = gpr_atm_no_barrier_load(&arena->size_so_far);
gpr_atm size = gpr_atm_no_barrier_load(&arena->total_used);
zone* z = arena->initial_zone.next;
gpr_free_aligned(arena);
while (z) {
@ -120,55 +121,25 @@ size_t gpr_arena_destroy(gpr_arena* arena) {
void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(size);
size_t previous_size_of_arena_allocations = static_cast<size_t>(
gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size));
size_t updated_size_of_arena_allocations =
previous_size_of_arena_allocations + size;
zone* z = &arena->initial_zone;
// Check to see if the allocation isn't able to end in the initial zone.
// This statement is true only in the uncommon case because of our arena
// sizing historesis (that is, most calls should have a large enough initial
// zone and will not need to grow the arena).
if (updated_size_of_arena_allocations > z->size_end) {
// Find a zone to fit this allocation
size_t begin = gpr_atm_no_barrier_fetch_add(&arena->total_used, size);
if (begin + size <= arena->initial_zone_size) {
return reinterpret_cast<char*>(arena) +
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + begin;
} else {
// If the allocation isn't able to end in the initial zone, create a new
// zone for this allocation, and any unused space in the initial zone is
// wasted. This overflowing and wasting is uncommon because of our arena
// sizing historesis (that is, most calls should have a large enough initial
// zone and will not need to grow the arena).
gpr_mu_lock(&arena->arena_growth_mutex);
while (updated_size_of_arena_allocations > z->size_end) {
if (z->next == nullptr) {
// Note that we do an extra increment of size_so_far to prevent multiple
// simultaneous callers from stepping on each other. However, this extra
// increment means some space in the arena is wasted.
// So whenever we need to allocate x bytes and there are x - n (where
// n > 0) remaining in the current zone, we will waste x bytes (x - n
// in the current zone and n in the new zone).
previous_size_of_arena_allocations = static_cast<size_t>(
gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size));
updated_size_of_arena_allocations =
previous_size_of_arena_allocations + size;
size_t next_z_size = updated_size_of_arena_allocations;
z->next = static_cast<zone*>(zalloc_aligned(
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)) + next_z_size));
z->next->size_begin = z->size_end;
z->next->size_end = z->size_end + next_z_size;
}
z = z->next;
}
zone* z = static_cast<zone*>(
zalloc_aligned(GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)) + size));
arena->last_zone->next = z;
arena->last_zone = z;
gpr_mu_unlock(&arena->arena_growth_mutex);
return reinterpret_cast<char*>(z) +
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone));
}
GPR_ASSERT(previous_size_of_arena_allocations >= z->size_begin);
GPR_ASSERT(updated_size_of_arena_allocations <= z->size_end);
// Skip the first part of the zone, which just contains tracking information.
// For the initial zone, this is the gpr_arena struct and for any other zone,
// it's the zone struct.
char* start_of_allocation_space =
(z == &arena->initial_zone)
? reinterpret_cast<char*>(arena) +
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena))
: reinterpret_cast<char*>(z) +
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone));
// previous_size_of_arena_allocations - size_begin is how many bytes have been
// allocated into the current zone
return start_of_allocation_space + previous_size_of_arena_allocations -
z->size_begin;
}
#endif // SIMPLE_ARENA_FOR_DEBUGGING

@ -157,11 +157,11 @@ class ThreadState {
} // namespace
void Fork::GlobalInit() {
if (!overrideEnabled_) {
if (!override_enabled_) {
#ifdef GRPC_ENABLE_FORK_SUPPORT
supportEnabled_ = true;
support_enabled_ = true;
#else
supportEnabled_ = false;
support_enabled_ = false;
#endif
bool env_var_set = false;
char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT");
@ -172,7 +172,7 @@ void Fork::GlobalInit() {
"False", "FALSE", "0"};
for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
if (0 == strcmp(env, truthy[i])) {
supportEnabled_ = true;
support_enabled_ = true;
env_var_set = true;
break;
}
@ -180,7 +180,7 @@ void Fork::GlobalInit() {
if (!env_var_set) {
for (size_t i = 0; i < GPR_ARRAY_SIZE(falsey); i++) {
if (0 == strcmp(env, falsey[i])) {
supportEnabled_ = false;
support_enabled_ = false;
env_var_set = true;
break;
}
@ -189,72 +189,80 @@ void Fork::GlobalInit() {
gpr_free(env);
}
}
if (supportEnabled_) {
execCtxState_ = grpc_core::New<internal::ExecCtxState>();
threadState_ = grpc_core::New<internal::ThreadState>();
if (support_enabled_) {
exec_ctx_state_ = grpc_core::New<internal::ExecCtxState>();
thread_state_ = grpc_core::New<internal::ThreadState>();
}
}
void Fork::GlobalShutdown() {
if (supportEnabled_) {
grpc_core::Delete(execCtxState_);
grpc_core::Delete(threadState_);
if (support_enabled_) {
grpc_core::Delete(exec_ctx_state_);
grpc_core::Delete(thread_state_);
}
}
bool Fork::Enabled() { return supportEnabled_; }
bool Fork::Enabled() { return support_enabled_; }
// Testing Only
void Fork::Enable(bool enable) {
overrideEnabled_ = true;
supportEnabled_ = enable;
override_enabled_ = true;
support_enabled_ = enable;
}
void Fork::IncExecCtxCount() {
if (supportEnabled_) {
execCtxState_->IncExecCtxCount();
if (support_enabled_) {
exec_ctx_state_->IncExecCtxCount();
}
}
void Fork::DecExecCtxCount() {
if (supportEnabled_) {
execCtxState_->DecExecCtxCount();
if (support_enabled_) {
exec_ctx_state_->DecExecCtxCount();
}
}
void Fork::SetResetChildPollingEngineFunc(
Fork::child_postfork_func reset_child_polling_engine) {
reset_child_polling_engine_ = reset_child_polling_engine;
}
Fork::child_postfork_func Fork::GetResetChildPollingEngineFunc() {
return reset_child_polling_engine_;
}
bool Fork::BlockExecCtx() {
if (supportEnabled_) {
return execCtxState_->BlockExecCtx();
if (support_enabled_) {
return exec_ctx_state_->BlockExecCtx();
}
return false;
}
void Fork::AllowExecCtx() {
if (supportEnabled_) {
execCtxState_->AllowExecCtx();
if (support_enabled_) {
exec_ctx_state_->AllowExecCtx();
}
}
void Fork::IncThreadCount() {
if (supportEnabled_) {
threadState_->IncThreadCount();
if (support_enabled_) {
thread_state_->IncThreadCount();
}
}
void Fork::DecThreadCount() {
if (supportEnabled_) {
threadState_->DecThreadCount();
if (support_enabled_) {
thread_state_->DecThreadCount();
}
}
void Fork::AwaitThreads() {
if (supportEnabled_) {
threadState_->AwaitThreads();
if (support_enabled_) {
thread_state_->AwaitThreads();
}
}
internal::ExecCtxState* Fork::execCtxState_ = nullptr;
internal::ThreadState* Fork::threadState_ = nullptr;
bool Fork::supportEnabled_ = false;
bool Fork::overrideEnabled_ = false;
internal::ExecCtxState* Fork::exec_ctx_state_ = nullptr;
internal::ThreadState* Fork::thread_state_ = nullptr;
bool Fork::support_enabled_ = false;
bool Fork::override_enabled_ = false;
Fork::child_postfork_func Fork::reset_child_polling_engine_ = nullptr;
} // namespace grpc_core

@ -33,6 +33,8 @@ class ThreadState;
class Fork {
public:
typedef void (*child_postfork_func)(void);
static void GlobalInit();
static void GlobalShutdown();
@ -46,6 +48,12 @@ class Fork {
// Decrement the count of active ExecCtxs
static void DecExecCtxCount();
// Provide a function that will be invoked in the child's postfork handler to
// reset the polling engine's internal state.
static void SetResetChildPollingEngineFunc(
child_postfork_func reset_child_polling_engine);
static child_postfork_func GetResetChildPollingEngineFunc();
// Check if there is a single active ExecCtx
// (the one used to invoke this function). If there are more,
// return false. Otherwise, return true and block creation of
@ -68,10 +76,11 @@ class Fork {
static void Enable(bool enable);
private:
static internal::ExecCtxState* execCtxState_;
static internal::ThreadState* threadState_;
static bool supportEnabled_;
static bool overrideEnabled_;
static internal::ExecCtxState* exec_ctx_state_;
static internal::ThreadState* thread_state_;
static bool support_enabled_;
static bool override_enabled_;
static child_postfork_func reset_child_polling_engine_;
};
} // namespace grpc_core

@ -131,6 +131,13 @@ static void epoll_set_shutdown() {
* Fd Declarations
*/
/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */
struct grpc_fork_fd_list {
grpc_fd* fd;
grpc_fd* next;
grpc_fd* prev;
};
struct grpc_fd {
int fd;
@ -141,6 +148,9 @@ struct grpc_fd {
struct grpc_fd* freelist_next;
grpc_iomgr_object iomgr_object;
/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */
grpc_fork_fd_list* fork_fd_list;
};
static void fd_global_init(void);
@ -256,6 +266,10 @@ static bool append_error(grpc_error** composite, grpc_error* error,
static grpc_fd* fd_freelist = nullptr;
static gpr_mu fd_freelist_mu;
/* Only used when GRPC_ENABLE_FORK_SUPPORT=1 */
static grpc_fd* fork_fd_list_head = nullptr;
static gpr_mu fork_fd_list_mu;
static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
static void fd_global_shutdown(void) {
@ -269,6 +283,38 @@ static void fd_global_shutdown(void) {
gpr_mu_destroy(&fd_freelist_mu);
}
static void fork_fd_list_add_grpc_fd(grpc_fd* fd) {
if (grpc_core::Fork::Enabled()) {
gpr_mu_lock(&fork_fd_list_mu);
fd->fork_fd_list =
static_cast<grpc_fork_fd_list*>(gpr_malloc(sizeof(grpc_fork_fd_list)));
fd->fork_fd_list->next = fork_fd_list_head;
fd->fork_fd_list->prev = nullptr;
if (fork_fd_list_head != nullptr) {
fork_fd_list_head->fork_fd_list->prev = fd;
}
fork_fd_list_head = fd;
gpr_mu_unlock(&fork_fd_list_mu);
}
}
static void fork_fd_list_remove_grpc_fd(grpc_fd* fd) {
if (grpc_core::Fork::Enabled()) {
gpr_mu_lock(&fork_fd_list_mu);
if (fork_fd_list_head == fd) {
fork_fd_list_head = fd->fork_fd_list->next;
}
if (fd->fork_fd_list->prev != nullptr) {
fd->fork_fd_list->prev->fork_fd_list->next = fd->fork_fd_list->next;
}
if (fd->fork_fd_list->next != nullptr) {
fd->fork_fd_list->next->fork_fd_list->prev = fd->fork_fd_list->prev;
}
gpr_free(fd->fork_fd_list);
gpr_mu_unlock(&fork_fd_list_mu);
}
}
static grpc_fd* fd_create(int fd, const char* name, bool track_err) {
grpc_fd* new_fd = nullptr;
@ -295,6 +341,7 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) {
char* fd_name;
gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
fork_fd_list_add_grpc_fd(new_fd);
#ifndef NDEBUG
if (grpc_trace_fd_refcount.enabled()) {
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name);
@ -361,6 +408,7 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd,
GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_REF(error));
grpc_iomgr_unregister_object(&fd->iomgr_object);
fork_fd_list_remove_grpc_fd(fd);
fd->read_closure->DestroyEvent();
fd->write_closure->DestroyEvent();
fd->error_closure->DestroyEvent();
@ -1190,6 +1238,10 @@ static void shutdown_engine(void) {
fd_global_shutdown();
pollset_global_shutdown();
epoll_set_shutdown();
if (grpc_core::Fork::Enabled()) {
gpr_mu_destroy(&fork_fd_list_mu);
grpc_core::Fork::SetResetChildPollingEngineFunc(nullptr);
}
}
static const grpc_event_engine_vtable vtable = {
@ -1227,6 +1279,21 @@ static const grpc_event_engine_vtable vtable = {
shutdown_engine,
};
/* Called by the child process's post-fork handler to close open fds, including
* the global epoll fd. This allows gRPC to shutdown in the child process
* without interfering with connections or RPCs ongoing in the parent. */
static void reset_event_manager_on_fork() {
gpr_mu_lock(&fork_fd_list_mu);
while (fork_fd_list_head != nullptr) {
close(fork_fd_list_head->fd);
fork_fd_list_head->fd = -1;
fork_fd_list_head = fork_fd_list_head->fork_fd_list->next;
}
gpr_mu_unlock(&fork_fd_list_mu);
shutdown_engine();
grpc_init_epoll1_linux(true);
}
/* It is possible that GLIBC has epoll but the underlying kernel doesn't.
* Create epoll_fd (epoll_set_init() takes care of that) to make sure epoll
* support is available */
@ -1248,6 +1315,11 @@ const grpc_event_engine_vtable* grpc_init_epoll1_linux(bool explicit_request) {
return nullptr;
}
if (grpc_core::Fork::Enabled()) {
gpr_mu_init(&fork_fd_list_mu);
grpc_core::Fork::SetResetChildPollingEngineFunc(
reset_event_manager_on_fork);
}
return &vtable;
}

@ -59,7 +59,14 @@ grpc_core::DebugOnlyTraceFlag grpc_polling_api_trace(false, "polling_api");
/** Default poll() function - a pointer so that it can be overridden by some
* tests */
#ifndef GPR_AIX
grpc_poll_function_type grpc_poll_function = poll;
#else
int aix_poll(struct pollfd fds[], nfds_t nfds, int timeout) {
return poll(fds, nfds, timeout);
}
grpc_poll_function_type grpc_poll_function = aix_poll;
#endif
grpc_wakeup_fd grpc_global_wakeup_fd;

@ -109,6 +109,12 @@ grpc_closure_scheduler* grpc_schedule_on_exec_ctx = &exec_ctx_scheduler;
namespace grpc_core {
GPR_TLS_CLASS_DEF(ExecCtx::exec_ctx_);
// WARNING: for testing purposes only!
void ExecCtx::TestOnlyGlobalInit(gpr_timespec new_val) {
g_start_time = new_val;
gpr_tls_init(&exec_ctx_);
}
void ExecCtx::GlobalInit(void) {
g_start_time = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_tls_init(&exec_ctx_);

@ -192,6 +192,8 @@ class ExecCtx {
now_is_valid_ = true;
}
static void TestOnlyGlobalInit(gpr_timespec new_val);
/** Global initialization for ExecCtx. Called by iomgr. */
static void GlobalInit(void);

@ -25,6 +25,7 @@
#include <string.h>
#include <grpc/fork.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/env.h"
@ -34,7 +35,6 @@
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/timer_manager.h"
#include "src/core/lib/iomgr/wakeup_fd_posix.h"
#include "src/core/lib/surface/init.h"
/*
* NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
@ -84,6 +84,11 @@ void grpc_postfork_child() {
if (!skipped_handler) {
grpc_core::Fork::AllowExecCtx();
grpc_core::ExecCtx exec_ctx;
grpc_core::Fork::child_postfork_func reset_polling_engine =
grpc_core::Fork::GetResetChildPollingEngineFunc();
if (reset_polling_engine != nullptr) {
reset_polling_engine();
}
grpc_timer_manager_set_threading(true);
grpc_executor_set_threading(true);
}

@ -140,6 +140,18 @@
#define GRPC_POSIX_SOCKET 1
#define GRPC_POSIX_SOCKETUTILS 1
#define GRPC_POSIX_WAKEUP_FD 1
#elif defined(GPR_SOLARIS)
#define GRPC_HAVE_UNIX_SOCKET 1
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1
#define GRPC_POSIX_SOCKET 1
#define GRPC_POSIX_SOCKETUTILS 1
#define GRPC_POSIX_WAKEUP_FD 1
#elif defined(GPR_AIX)
#define GRPC_HAVE_UNIX_SOCKET 1
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1
#define GRPC_POSIX_SOCKET 1
#define GRPC_POSIX_SOCKETUTILS 1
#define GRPC_POSIX_WAKEUP_FD 1
#elif defined(GPR_NACL)
#define GRPC_HAVE_ARPA_NAMESER 1
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1

@ -57,7 +57,7 @@ int grpc_socket_mutator_compare(grpc_socket_mutator* a,
void grpc_socket_mutator_unref(grpc_socket_mutator* mutator) {
if (gpr_unref(&mutator->refcount)) {
mutator->vtable->destory(mutator);
mutator->vtable->destroy(mutator);
}
}

@ -33,7 +33,7 @@ typedef struct {
/** Compare socket mutator \a a and \a b */
int (*compare)(grpc_socket_mutator* a, grpc_socket_mutator* b);
/** Destroys the socket mutator instance */
void (*destory)(grpc_socket_mutator* mutator);
void (*destroy)(grpc_socket_mutator* mutator);
} grpc_socket_mutator_vtable;
/** The Socket Mutator interface allows changes on socket options */

@ -61,10 +61,11 @@ typedef struct grpc_timer_vtable {
/* Initialize *timer. When expired or canceled, closure will be called with
error set to indicate if it expired (GRPC_ERROR_NONE) or was canceled
(GRPC_ERROR_CANCELLED). timer_cb is guaranteed to be called exactly once, and
(GRPC_ERROR_CANCELLED). *closure is guaranteed to be called exactly once, and
application code should check the error to determine how it was invoked. The
application callback is also responsible for maintaining information about
when to free up any user-level state. */
when to free up any user-level state. Behavior is undefined for a deadline of
GRPC_MILLIS_INF_FUTURE. */
void grpc_timer_init(grpc_timer* timer, grpc_millis deadline,
grpc_closure* closure);

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h>
#include "src/core/tsi/grpc_shadow_boringssl.h"
#include <grpc/slice.h>
#include <openssl/rsa.h>

@ -18,6 +18,8 @@
#include <grpc/support/port_platform.h>
#include "src/core/tsi/grpc_shadow_boringssl.h"
#include "src/core/lib/security/credentials/jwt/jwt_verifier.h"
#include <limits.h>

@ -235,7 +235,7 @@ static void on_oauth2_token_fetcher_http_response(void* user_data,
access_token_md);
} else {
error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Error occured when fetching oauth2 token.", &error, 1);
"Error occurred when fetching oauth2 token.", &error, 1);
}
GRPC_CLOSURE_SCHED(pending_request->on_request_metadata, error);
grpc_polling_entity_del_from_pollset_set(

@ -1951,7 +1951,7 @@ done:
return error;
done_with_error:
/* reverse any mutations that occured */
/* reverse any mutations that occurred */
if (stream_op->send_initial_metadata) {
call->sent_initial_metadata = false;
grpc_metadata_batch_clear(&call->metadata_batch[0][0]);

@ -22,6 +22,5 @@
void grpc_register_security_filters(void);
void grpc_security_pre_init(void);
void grpc_security_init(void);
int grpc_is_initialized(void);
#endif /* GRPC_CORE_LIB_SURFACE_INIT_H */

@ -65,8 +65,8 @@ const char* ServiceConfig::GetLoadBalancingPolicyName() const {
return lb_policy_name;
}
size_t ServiceConfig::CountNamesInMethodConfig(grpc_json* json) {
size_t num_names = 0;
int ServiceConfig::CountNamesInMethodConfig(grpc_json* json) {
int num_names = 0;
for (grpc_json* field = json->child; field != nullptr; field = field->next) {
if (field->key != nullptr && strcmp(field->key, "name") == 0) {
if (field->type != GRPC_JSON_ARRAY) return -1;

@ -103,7 +103,7 @@ class ServiceConfig {
ServiceConfig(UniquePtr<char> json_string, grpc_json* json_tree);
// Returns the number of names specified in the method config \a json.
static size_t CountNamesInMethodConfig(grpc_json* json);
static int CountNamesInMethodConfig(grpc_json* json);
// Returns a path string for the JSON name object specified by \a json.
// Returns null on error.
@ -188,9 +188,9 @@ ServiceConfig::CreateMethodConfigTable(CreateValue<T> create_value) {
// Find number of entries.
for (grpc_json* method = field->child; method != nullptr;
method = method->next) {
size_t count = CountNamesInMethodConfig(method);
int count = CountNamesInMethodConfig(method);
if (count <= 0) return nullptr;
num_entries += count;
num_entries += static_cast<size_t>(count);
}
// Populate method config table entries.
entries = static_cast<typename SliceHashTable<RefCountedPtr<T>>::Entry*>(

@ -18,6 +18,8 @@
#include <grpc/support/port_platform.h>
#include "src/core/tsi/grpc_shadow_boringssl.h"
#include "src/core/tsi/alts/crypt/gsec.h"
#include <openssl/bio.h>

File diff suppressed because it is too large Load Diff

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h>
#include "src/core/tsi/grpc_shadow_boringssl.h"
#include <grpc/slice.h>
extern "C" {

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h>
#include "src/core/tsi/grpc_shadow_boringssl.h"
#include <grpc/slice.h>
#include <grpc/support/sync.h>

@ -18,6 +18,8 @@
#include <grpc/support/port_platform.h>
#include "src/core/tsi/grpc_shadow_boringssl.h"
#include "src/core/tsi/ssl_transport_security.h"
#include <limits.h>
@ -216,7 +218,7 @@ static void ssl_log_where_info(const SSL* ssl, int where, int flag,
/* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */
static void ssl_info_callback(const SSL* ssl, int where, int ret) {
if (ret == 0) {
gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n");
gpr_log(GPR_ERROR, "ssl_info_callback: error occurred.\n");
return;
}

@ -29,6 +29,8 @@
#include <grpc/support/port_platform.h>
#include "src/core/tsi/grpc_shadow_boringssl.h"
#include <openssl/ssl.h>
#ifdef OPENSSL_IS_BORINGSSL

@ -24,15 +24,11 @@
#include "absl/strings/string_view.h"
#include "include/grpcpp/opencensus.h"
#include "opencensus/stats/stats.h"
#include "opencensus/trace/span.h"
namespace grpc {
class ServerContext;
// Returns the tracing Span for the current RPC.
::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context);
// The tag keys set when recording RPC stats.
::opencensus::stats::TagKey ClientMethodTagKey();
::opencensus::stats::TagKey ClientStatusTagKey();

@ -108,7 +108,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
Logger.Error(e, "Exception occured while invoking completion delegate.");
Logger.Error(e, "Exception occurred while invoking completion delegate.");
}
}
finally

@ -144,7 +144,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
Logger.Error(e, "Exception occured while invoking batch completion delegate.");
Logger.Error(e, "Exception occurred while invoking batch completion delegate.");
}
finally
{

@ -189,7 +189,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
Logger.Error(e, "Exception occured while extracting event from completion registry.");
Logger.Error(e, "Exception occurred while extracting event from completion registry.");
}
}
}
@ -233,7 +233,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
Logger.Error(e, "Exception occured while invoking completion delegate");
Logger.Error(e, "Exception occurred while invoking completion delegate");
}
finally
{

@ -112,7 +112,7 @@ namespace Grpc.Core.Internal
}
catch (Exception e)
{
Logger.Error(e, "Exception occured while invoking request call completion delegate.");
Logger.Error(e, "Exception occurred while invoking request call completion delegate.");
}
finally
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -220,3 +220,25 @@ Objective-C Protobuf runtime library.
[gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
[example Podfile]:https://github.com/grpc/grpc/blob/master/examples/objective-c/helloworld/Podfile
[example apps]: https://github.com/grpc/grpc/tree/master/examples/objective-c
## Use gRPC with OpenSSL
gRPC uses BoringSSL as its dependency, which is a fork of OpenSSL and export a number of symbols
that are the same as OpenSSL. gRPC avoids conflicts of these symbols by renaming BoringSSL symbols.
If you need gRPC to use OpenSSL instead of BoringSSL (e.g. for the benefit of reducing the binary
size of your product), you need to make a local `gRPC-Core` podspec and tweak it accordingly:
- Copy the version of `/gRPC-Core.podspec` you wish to use from Github into the repository of your
app;
- In your `Podfile`, add the following line:
```
pod `gRPC-Core`, :podspec => "." # assuming gRPC-Core.podspec is in the same directory as your Podfile
```
- Remove [the
macro](https://github.com/grpc/grpc/blob/b24b212ee585d376c618235905757b2445ac6461/gRPC-Core.podspec#L186)
`GRPC_SHADOW_BORINGSSL_SYMBOLS` to disable symbol renaming;
- Substitude the `BoringSSL-GRPC`
[dependency](https://github.com/grpc/grpc/blob/b24b212ee585d376c618235905757b2445ac6461/gRPC-Core.podspec#L184)
to whatever pod of OpenSSL your other libraries use.
These steps should allow gRPC to use OpenSSL and drop BoringSSL dependency. If you see any issue,
file an issue to us.

@ -19,7 +19,7 @@ target 'Sample' do
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'gRPC', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core', :path => GRPC_LOCAL_SRC

@ -19,7 +19,7 @@ target 'SwiftSample' do
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'gRPC', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core', :path => GRPC_LOCAL_SRC

File diff suppressed because it is too large Load Diff

@ -10,7 +10,7 @@ target 'ConnectivityTestingApp' do
pod 'gRPC-ProtoRPC/CFStream', :path => GRPC_LOCAL_SRC
pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
end
pre_install do |installer|

@ -37,7 +37,9 @@
#import "test/core/end2end/data/ssl_test_data.h"
#import "test/core/util/test_config.h"
#import <BoringSSL/openssl/ssl.h>
#import "src/core/tsi/grpc_shadow_boringssl.h"
#import <openssl/ssl.h>
static void drain_cq(grpc_completion_queue *cq) {
grpc_event ev;

@ -21,7 +21,7 @@ GRPC_LOCAL_SRC = '../../..'
pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
pod 'gRPC', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
@ -47,7 +47,7 @@ end
pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
pod 'gRPC/CFStream', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core/CFStream-Implementation', :path => GRPC_LOCAL_SRC
@ -62,7 +62,7 @@ end
CronetUnitTests
).each do |target_name|
target target_name do
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core/Cronet-Interface', :path => GRPC_LOCAL_SRC

@ -1716,6 +1716,14 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_TESTABILITY = YES;
GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"COCOAPODS=1",
"$(inherited)",
"PB_FIELD_32BIT=1",
"PB_NO_PACKED_STRUCTS=1",
"GRPC_SHADOW_BORINGSSL_SYMBOLS=1",
);
INFOPLIST_FILE = CronetUnitTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";

@ -270,7 +270,7 @@ class PersistentListTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelDefaultOutBound1()
{
$this->channel1 = new Grpc\Channel('localhost:10011', []);
$this->channel1 = new Grpc\Channel('localhost:10004', []);
// Make channel1 not IDLE.
$this->channel1->getConnectivityState(true);
$this->waitUntilNotIdle($this->channel1);
@ -280,7 +280,7 @@ class PersistentListTest extends PHPUnit_Framework_TestCase
// Since channel1 is CONNECTING, channel 2 will not be persisted
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10011',
$this->channel2 = new Grpc\Channel('localhost:10004',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
@ -295,7 +295,7 @@ class PersistentListTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelDefaultOutBound2()
{
$this->channel1 = new Grpc\Channel('localhost:10011', []);
$this->channel1 = new Grpc\Channel('localhost:10005', []);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
@ -303,7 +303,7 @@ class PersistentListTest extends PHPUnit_Framework_TestCase
// gRPC channel. channel2 will not be persisted
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10011',
$this->channel2 = new Grpc\Channel('localhost:10005',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
@ -318,7 +318,7 @@ class PersistentListTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelDefaultOutBound3()
{
$this->channel1 = new Grpc\Channel('localhost:10011', []);
$this->channel1 = new Grpc\Channel('localhost:10006', []);
$channel1_info = $this->channel1->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel1_info['connectivity_status']);
@ -327,7 +327,7 @@ class PersistentListTest extends PHPUnit_Framework_TestCase
// channel2 can be persisted.
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10011',
$this->channel2 = new Grpc\Channel('localhost:10006',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);
@ -342,7 +342,7 @@ class PersistentListTest extends PHPUnit_Framework_TestCase
public function testPersistentChannelTwoUpperBound()
{
$this->channel1 = new Grpc\Channel('localhost:10011', [
$this->channel1 = new Grpc\Channel('localhost:10007', [
"grpc_target_persist_bound" => 2,
]);
$channel1_info = $this->channel1->getChannelInfo();
@ -351,7 +351,7 @@ class PersistentListTest extends PHPUnit_Framework_TestCase
// Since channel1 is IDLE, channel 1 will be deleted
$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null,
null);
$this->channel2 = new Grpc\Channel('localhost:10011',
$this->channel2 = new Grpc\Channel('localhost:10007',
['credentials' => $channel_credentials]);
$channel2_info = $this->channel2->getChannelInfo();
$this->assertEquals(GRPC\CHANNEL_IDLE, $channel2_info['connectivity_status']);

@ -265,8 +265,17 @@ class BuildExt(build_ext.build_ext):
os.path.join(target_path, 'libgpr.a'),
os.path.join(target_path, 'libgrpc.a')
]
# Running make separately for Mac means we lose all
# Extension.define_macros configured in setup.py. Re-add the macro
# for gRPC Core's fork handlers.
# TODO(ericgribkoff) Decide what to do about the other missing core
# macros, including GRPC_ENABLE_FORK_SUPPORT, which defaults to 1
# on Linux but remains unset on Mac.
extra_defines = [
'EXTRA_DEFINES="GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1"'
]
make_process = subprocess.Popen(
['make'] + targets,
['make'] + extra_defines + targets,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
make_out, make_err = make_process.communicate()

@ -111,6 +111,10 @@ class _RPCState(object):
# prior to termination of the RPC.
self.cancelled = False
self.callbacks = []
self.fork_epoch = cygrpc.get_fork_epoch()
def reset_postfork_child(self):
self.condition = threading.Condition()
def _abort(state, code, details):
@ -166,21 +170,30 @@ def _event_handler(state, response_deserializer):
done = not state.due
for callback in callbacks:
callback()
return done
return done and state.fork_epoch >= cygrpc.get_fork_epoch()
return handle_event
def _consume_request_iterator(request_iterator, state, call, request_serializer,
event_handler):
if cygrpc.is_fork_support_enabled():
condition_wait_timeout = 1.0
else:
condition_wait_timeout = None
def consume_request_iterator(): # pylint: disable=too-many-branches
while True:
return_from_user_request_generator_invoked = False
try:
# The thread may die in user-code. Do not block fork for this.
cygrpc.enter_user_request_generator()
request = next(request_iterator)
except StopIteration:
break
except Exception: # pylint: disable=broad-except
cygrpc.return_from_user_request_generator()
return_from_user_request_generator_invoked = True
code = grpc.StatusCode.UNKNOWN
details = 'Exception iterating requests!'
_LOGGER.exception(details)
@ -188,6 +201,9 @@ def _consume_request_iterator(request_iterator, state, call, request_serializer,
details)
_abort(state, code, details)
return
finally:
if not return_from_user_request_generator_invoked:
cygrpc.return_from_user_request_generator()
serialized_request = _common.serialize(request, request_serializer)
with state.condition:
if state.code is None and not state.cancelled:
@ -208,7 +224,8 @@ def _consume_request_iterator(request_iterator, state, call, request_serializer,
else:
return
while True:
state.condition.wait()
state.condition.wait(condition_wait_timeout)
cygrpc.block_if_fork_in_progress(state)
if state.code is None:
if cygrpc.OperationType.send_message not in state.due:
break
@ -224,8 +241,9 @@ def _consume_request_iterator(request_iterator, state, call, request_serializer,
if operating:
state.due.add(cygrpc.OperationType.send_close_from_client)
consumption_thread = threading.Thread(target=consume_request_iterator)
consumption_thread.daemon = True
consumption_thread = cygrpc.ForkManagedThread(
target=consume_request_iterator)
consumption_thread.setDaemon(True)
consumption_thread.start()
@ -671,13 +689,20 @@ class _ChannelCallState(object):
self.lock = threading.Lock()
self.channel = channel
self.managed_calls = 0
self.threading = False
def reset_postfork_child(self):
self.managed_calls = 0
def _run_channel_spin_thread(state):
def channel_spin():
while True:
cygrpc.block_if_fork_in_progress(state)
event = state.channel.next_call_event()
if event.completion_type == cygrpc.CompletionType.queue_timeout:
continue
call_completed = event.tag(event)
if call_completed:
with state.lock:
@ -685,8 +710,8 @@ def _run_channel_spin_thread(state):
if state.managed_calls == 0:
return
channel_spin_thread = threading.Thread(target=channel_spin)
channel_spin_thread.daemon = True
channel_spin_thread = cygrpc.ForkManagedThread(target=channel_spin)
channel_spin_thread.setDaemon(True)
channel_spin_thread.start()
@ -742,6 +767,13 @@ class _ChannelConnectivityState(object):
self.callbacks_and_connectivities = []
self.delivering = False
def reset_postfork_child(self):
self.polling = False
self.connectivity = None
self.try_to_connect = False
self.callbacks_and_connectivities = []
self.delivering = False
def _deliveries(state):
callbacks_needing_update = []
@ -758,6 +790,7 @@ def _deliver(state, initial_connectivity, initial_callbacks):
callbacks = initial_callbacks
while True:
for callback in callbacks:
cygrpc.block_if_fork_in_progress(state)
callable_util.call_logging_exceptions(
callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE,
connectivity)
@ -771,7 +804,7 @@ def _deliver(state, initial_connectivity, initial_callbacks):
def _spawn_delivery(state, callbacks):
delivering_thread = threading.Thread(
delivering_thread = cygrpc.ForkManagedThread(
target=_deliver, args=(
state,
state.connectivity,
@ -799,6 +832,7 @@ def _poll_connectivity(state, channel, initial_try_to_connect):
while True:
event = channel.watch_connectivity_state(connectivity,
time.time() + 0.2)
cygrpc.block_if_fork_in_progress(state)
with state.lock:
if not state.callbacks_and_connectivities and not state.try_to_connect:
state.polling = False
@ -826,10 +860,10 @@ def _moot(state):
def _subscribe(state, callback, try_to_connect):
with state.lock:
if not state.callbacks_and_connectivities and not state.polling:
polling_thread = threading.Thread(
polling_thread = cygrpc.ForkManagedThread(
target=_poll_connectivity,
args=(state, state.channel, bool(try_to_connect)))
polling_thread.daemon = True
polling_thread.setDaemon(True)
polling_thread.start()
state.polling = True
state.callbacks_and_connectivities.append([callback, None])
@ -876,6 +910,7 @@ class Channel(grpc.Channel):
_common.encode(target), _options(options), credentials)
self._call_state = _ChannelCallState(self._channel)
self._connectivity_state = _ChannelConnectivityState(self._channel)
cygrpc.fork_register_channel(self)
def subscribe(self, callback, try_to_connect=None):
_subscribe(self._connectivity_state, callback, try_to_connect)
@ -919,6 +954,11 @@ class Channel(grpc.Channel):
self._channel.close(cygrpc.StatusCode.cancelled, 'Channel closed!')
_moot(self._connectivity_state)
def _close_on_fork(self):
self._channel.close_on_fork(cygrpc.StatusCode.cancelled,
'Channel closed due to fork')
_moot(self._connectivity_state)
def __enter__(self):
return self
@ -939,4 +979,5 @@ class Channel(grpc.Channel):
# for as long as they are in use and to close them after using them,
# then deletion of this grpc._channel.Channel instance can be made to
# effect closure of the underlying cygrpc.Channel instance.
cygrpc.fork_unregister_channel(self)
_moot(self._connectivity_state)

@ -19,7 +19,7 @@ cdef class Call:
def __cinit__(self):
# Create an *empty* call
grpc_init()
fork_handlers_and_grpc_init()
self.c_call = NULL
self.references = []

@ -40,6 +40,7 @@ cdef class _ChannelState:
# field and just use the NULLness of c_channel as an indication that the
# channel is closed.
cdef object open
cdef object closed_reason
# A dict from _BatchOperationTag to _CallState
cdef dict integrated_call_states

@ -15,6 +15,7 @@
cimport cpython
import threading
import time
_INTERNAL_CALL_ERROR_MESSAGE_FORMAT = (
'Internal gRPC call error %d. ' +
@ -83,6 +84,7 @@ cdef class _ChannelState:
self.integrated_call_states = {}
self.segregated_call_states = set()
self.connectivity_due = set()
self.closed_reason = None
cdef tuple _operate(grpc_call *c_call, object operations, object user_tag):
@ -142,10 +144,10 @@ cdef _cancel(
_check_and_raise_call_error_no_metadata(c_call_error)
cdef BatchOperationEvent _next_call_event(
cdef _next_call_event(
_ChannelState channel_state, grpc_completion_queue *c_completion_queue,
on_success):
tag, event = _latent_event(c_completion_queue, None)
on_success, deadline):
tag, event = _latent_event(c_completion_queue, deadline)
with channel_state.condition:
on_success(tag)
channel_state.condition.notify_all()
@ -229,8 +231,7 @@ cdef void _call(
call_state.due.update(started_tags)
on_success(started_tags)
else:
raise ValueError('Cannot invoke RPC on closed channel!')
raise ValueError('Cannot invoke RPC: %s' % channel_state.closed_reason)
cdef void _process_integrated_call_tag(
_ChannelState state, _BatchOperationTag tag) except *:
cdef _CallState call_state = state.integrated_call_states.pop(tag)
@ -302,7 +303,7 @@ cdef class SegregatedCall:
_process_segregated_call_tag(
self._channel_state, self._call_state, self._c_completion_queue, tag)
return _next_call_event(
self._channel_state, self._c_completion_queue, on_success)
self._channel_state, self._c_completion_queue, on_success, None)
cdef SegregatedCall _segregated_call(
@ -346,7 +347,7 @@ cdef object _watch_connectivity_state(
state.c_connectivity_completion_queue, <cpython.PyObject *>tag)
state.connectivity_due.add(tag)
else:
raise ValueError('Cannot invoke RPC on closed channel!')
raise ValueError('Cannot invoke RPC: %s' % state.closed_reason)
completed_tag, event = _latent_event(
state.c_connectivity_completion_queue, None)
with state.condition:
@ -355,12 +356,15 @@ cdef object _watch_connectivity_state(
return event
cdef _close(_ChannelState state, grpc_status_code code, object details):
cdef _close(Channel channel, grpc_status_code code, object details,
drain_calls):
cdef _ChannelState state = channel._state
cdef _CallState call_state
encoded_details = _encode(details)
with state.condition:
if state.open:
state.open = False
state.closed_reason = details
for call_state in set(state.integrated_call_states.values()):
grpc_call_cancel_with_status(
call_state.c_call, code, encoded_details, NULL)
@ -370,12 +374,19 @@ cdef _close(_ChannelState state, grpc_status_code code, object details):
# TODO(https://github.com/grpc/grpc/issues/3064): Cancel connectivity
# watching.
while state.integrated_call_states:
state.condition.wait()
while state.segregated_call_states:
state.condition.wait()
while state.connectivity_due:
state.condition.wait()
if drain_calls:
while not _calls_drained(state):
event = channel.next_call_event()
if event.completion_type == CompletionType.queue_timeout:
continue
event.tag(event)
else:
while state.integrated_call_states:
state.condition.wait()
while state.segregated_call_states:
state.condition.wait()
while state.connectivity_due:
state.condition.wait()
_destroy_c_completion_queue(state.c_call_completion_queue)
_destroy_c_completion_queue(state.c_connectivity_completion_queue)
@ -390,13 +401,17 @@ cdef _close(_ChannelState state, grpc_status_code code, object details):
state.condition.wait()
cdef _calls_drained(_ChannelState state):
return not (state.integrated_call_states or state.segregated_call_states or
state.connectivity_due)
cdef class Channel:
def __cinit__(
self, bytes target, object arguments,
ChannelCredentials channel_credentials):
arguments = () if arguments is None else tuple(arguments)
grpc_init()
fork_handlers_and_grpc_init()
self._state = _ChannelState()
self._vtable.copy = &_copy_pointer
self._vtable.destroy = &_destroy_pointer
@ -435,9 +450,14 @@ cdef class Channel:
def next_call_event(self):
def on_success(tag):
_process_integrated_call_tag(self._state, tag)
return _next_call_event(
self._state, self._state.c_call_completion_queue, on_success)
if tag is not None:
_process_integrated_call_tag(self._state, tag)
if is_fork_support_enabled():
queue_deadline = time.time() + 1.0
else:
queue_deadline = None
return _next_call_event(self._state, self._state.c_call_completion_queue,
on_success, queue_deadline)
def segregated_call(
self, int flags, method, host, object deadline, object metadata,
@ -452,11 +472,14 @@ cdef class Channel:
return grpc_channel_check_connectivity_state(
self._state.c_channel, try_to_connect)
else:
raise ValueError('Cannot invoke RPC on closed channel!')
raise ValueError('Cannot invoke RPC: %s' % self._state.closed_reason)
def watch_connectivity_state(
self, grpc_connectivity_state last_observed_state, object deadline):
return _watch_connectivity_state(self._state, last_observed_state, deadline)
def close(self, code, details):
_close(self._state, code, details)
_close(self, code, details, False)
def close_on_fork(self, code, details):
_close(self, code, details, True)

@ -71,7 +71,7 @@ cdef class CompletionQueue:
def __cinit__(self, shutdown_cq=False):
cdef grpc_completion_queue_attributes c_attrs
grpc_init()
fork_handlers_and_grpc_init()
if shutdown_cq:
c_attrs.version = 1
c_attrs.cq_completion_type = GRPC_CQ_NEXT

@ -21,7 +21,7 @@ from libc.stdint cimport uintptr_t
def _spawn_callback_in_thread(cb_func, args):
threading.Thread(target=cb_func, args=args).start()
ForkManagedThread(target=cb_func, args=args).start()
async_callback_func = _spawn_callback_in_thread
@ -114,7 +114,7 @@ cdef class ChannelCredentials:
cdef class SSLSessionCacheLRU:
def __cinit__(self, capacity):
grpc_init()
fork_handlers_and_grpc_init()
self._cache = grpc_ssl_session_cache_create_lru(capacity)
def __int__(self):
@ -172,7 +172,7 @@ cdef class CompositeChannelCredentials(ChannelCredentials):
cdef class ServerCertificateConfig:
def __cinit__(self):
grpc_init()
fork_handlers_and_grpc_init()
self.c_cert_config = NULL
self.c_pem_root_certs = NULL
self.c_ssl_pem_key_cert_pairs = NULL
@ -187,7 +187,7 @@ cdef class ServerCertificateConfig:
cdef class ServerCredentials:
def __cinit__(self):
grpc_init()
fork_handlers_and_grpc_init()
self.c_credentials = NULL
self.references = []
self.initial_cert_config = None
@ -282,3 +282,41 @@ def server_credentials_ssl_dynamic_cert_config(initial_cert_config,
# C-core assumes ownership of c_options
credentials.c_credentials = grpc_ssl_server_credentials_create_with_options(c_options)
return credentials
cdef grpc_ssl_certificate_config_reload_status _server_cert_config_fetcher_wrapper(
void* user_data, grpc_ssl_server_certificate_config **config) with gil:
# This is a credentials.ServerCertificateConfig
cdef ServerCertificateConfig cert_config = None
if not user_data:
raise ValueError('internal error: user_data must be specified')
credentials = <ServerCredentials>user_data
if not credentials.initial_cert_config_fetched:
# C-core is asking for the initial cert config
credentials.initial_cert_config_fetched = True
cert_config = credentials.initial_cert_config._certificate_configuration
else:
user_cb = credentials.cert_config_fetcher
try:
cert_config_wrapper = user_cb()
except Exception:
_LOGGER.exception('Error fetching certificate config')
return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL
if cert_config_wrapper is None:
return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED
elif not isinstance(
cert_config_wrapper, grpc.ServerCertificateConfiguration):
_LOGGER.error(
'Error fetching certificate configuration: certificate '
'configuration must be of type grpc.ServerCertificateConfiguration, '
'not %s' % type(cert_config_wrapper).__name__)
return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL
else:
cert_config = cert_config_wrapper._certificate_configuration
config[0] = <grpc_ssl_server_certificate_config*>cert_config.c_cert_config
# our caller will assume ownership of memory, so we have to recreate
# a copy of c_cert_config here
cert_config.c_cert_config = grpc_ssl_server_certificate_config_create(
cert_config.c_pem_root_certs, cert_config.c_ssl_pem_key_cert_pairs,
cert_config.c_ssl_pem_key_cert_pairs_count)
return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW

@ -0,0 +1,29 @@
# Copyright 2018 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.
cdef extern from "pthread.h" nogil:
int pthread_atfork(
void (*prepare)() nogil,
void (*parent)() nogil,
void (*child)() nogil)
cdef void __prefork() nogil
cdef void __postfork_parent() nogil
cdef void __postfork_child() nogil

@ -0,0 +1,207 @@
# Copyright 2018 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.
import logging
import os
import threading
_LOGGER = logging.getLogger(__name__)
_AWAIT_THREADS_TIMEOUT_SECONDS = 5
_TRUE_VALUES = ['yes', 'Yes', 'YES', 'true', 'True', 'TRUE', '1']
# This flag enables experimental support within gRPC Python for applications
# that will fork() without exec(). When enabled, gRPC Python will attempt to
# pause all of its internally created threads before the fork syscall proceeds.
#
# For this to be successful, the application must not have multiple threads of
# its own calling into gRPC when fork is invoked. Any callbacks from gRPC
# Python-spawned threads into user code (e.g., callbacks for asynchronous RPCs)
# must not block and should execute quickly.
#
# This flag is not supported on Windows.
_GRPC_ENABLE_FORK_SUPPORT = (
os.environ.get('GRPC_ENABLE_FORK_SUPPORT', '0')
.lower() in _TRUE_VALUES)
_GRPC_POLL_STRATEGY = os.environ.get('GRPC_POLL_STRATEGY')
cdef void __prefork() nogil:
with gil:
with _fork_state.fork_in_progress_condition:
_fork_state.fork_in_progress = True
if not _fork_state.active_thread_count.await_zero_threads(
_AWAIT_THREADS_TIMEOUT_SECONDS):
_LOGGER.error(
'Failed to shutdown gRPC Python threads prior to fork. '
'Behavior after fork will be undefined.')
cdef void __postfork_parent() nogil:
with gil:
with _fork_state.fork_in_progress_condition:
_fork_state.fork_in_progress = False
_fork_state.fork_in_progress_condition.notify_all()
cdef void __postfork_child() nogil:
with gil:
# Thread could be holding the fork_in_progress_condition inside of
# block_if_fork_in_progress() when fork occurs. Reset the lock here.
_fork_state.fork_in_progress_condition = threading.Condition()
# A thread in return_from_user_request_generator() may hold this lock
# when fork occurs.
_fork_state.active_thread_count = _ActiveThreadCount()
for state_to_reset in _fork_state.postfork_states_to_reset:
state_to_reset.reset_postfork_child()
_fork_state.fork_epoch += 1
for channel in _fork_state.channels:
channel._close_on_fork()
# TODO(ericgribkoff) Check and abort if core is not shutdown
with _fork_state.fork_in_progress_condition:
_fork_state.fork_in_progress = False
if grpc_is_initialized() > 0:
with gil:
_LOGGER.error('Failed to shutdown gRPC Core after fork()')
os._exit(os.EX_USAGE)
def fork_handlers_and_grpc_init():
grpc_init()
if _GRPC_ENABLE_FORK_SUPPORT:
# TODO(ericgribkoff) epoll1 is default for grpcio distribution. Decide whether to expose
# grpc_get_poll_strategy_name() from ev_posix.cc to get actual polling choice.
if _GRPC_POLL_STRATEGY is not None and _GRPC_POLL_STRATEGY != "epoll1":
_LOGGER.error(
'gRPC Python fork support is only compatible with the epoll1 '
'polling engine')
return
with _fork_state.fork_handler_registered_lock:
if not _fork_state.fork_handler_registered:
pthread_atfork(&__prefork, &__postfork_parent, &__postfork_child)
_fork_state.fork_handler_registered = True
class ForkManagedThread(object):
def __init__(self, target, args=()):
if _GRPC_ENABLE_FORK_SUPPORT:
def managed_target(*args):
try:
target(*args)
finally:
_fork_state.active_thread_count.decrement()
self._thread = threading.Thread(target=managed_target, args=args)
else:
self._thread = threading.Thread(target=target, args=args)
def setDaemon(self, daemonic):
self._thread.daemon = daemonic
def start(self):
if _GRPC_ENABLE_FORK_SUPPORT:
_fork_state.active_thread_count.increment()
self._thread.start()
def join(self):
self._thread.join()
def block_if_fork_in_progress(postfork_state_to_reset=None):
if _GRPC_ENABLE_FORK_SUPPORT:
with _fork_state.fork_in_progress_condition:
if not _fork_state.fork_in_progress:
return
if postfork_state_to_reset is not None:
_fork_state.postfork_states_to_reset.append(postfork_state_to_reset)
_fork_state.active_thread_count.decrement()
_fork_state.fork_in_progress_condition.wait()
_fork_state.active_thread_count.increment()
def enter_user_request_generator():
if _GRPC_ENABLE_FORK_SUPPORT:
_fork_state.active_thread_count.decrement()
def return_from_user_request_generator():
if _GRPC_ENABLE_FORK_SUPPORT:
_fork_state.active_thread_count.increment()
block_if_fork_in_progress()
def get_fork_epoch():
return _fork_state.fork_epoch
def is_fork_support_enabled():
return _GRPC_ENABLE_FORK_SUPPORT
def fork_register_channel(channel):
if _GRPC_ENABLE_FORK_SUPPORT:
_fork_state.channels.add(channel)
def fork_unregister_channel(channel):
if _GRPC_ENABLE_FORK_SUPPORT:
_fork_state.channels.remove(channel)
class _ActiveThreadCount(object):
def __init__(self):
self._num_active_threads = 0
self._condition = threading.Condition()
def increment(self):
with self._condition:
self._num_active_threads += 1
def decrement(self):
with self._condition:
self._num_active_threads -= 1
if self._num_active_threads == 0:
self._condition.notify_all()
def await_zero_threads(self, timeout_secs):
end_time = time.time() + timeout_secs
wait_time = timeout_secs
with self._condition:
while True:
if self._num_active_threads > 0:
self._condition.wait(wait_time)
if self._num_active_threads == 0:
return True
# Thread count may have increased before this re-obtains the
# lock after a notify(). Wait again until timeout_secs has
# elapsed.
wait_time = end_time - time.time()
if wait_time <= 0:
return False
class _ForkState(object):
def __init__(self):
self.fork_in_progress_condition = threading.Condition()
self.fork_in_progress = False
self.postfork_states_to_reset = []
self.fork_handler_registered_lock = threading.Lock()
self.fork_handler_registered = False
self.active_thread_count = _ActiveThreadCount()
self.fork_epoch = 0
self.channels = set()
_fork_state = _ForkState()

@ -0,0 +1,63 @@
# Copyright 2018 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.
import threading
# No-op implementations for Windows.
def fork_handlers_and_grpc_init():
grpc_init()
class ForkManagedThread(object):
def __init__(self, target, args=()):
self._thread = threading.Thread(target=target, args=args)
def setDaemon(self, daemonic):
self._thread.daemon = daemonic
def start(self):
self._thread.start()
def join(self):
self._thread.join()
def block_if_fork_in_progress(postfork_state_to_reset=None):
pass
def enter_user_request_generator():
pass
def return_from_user_request_generator():
pass
def get_fork_epoch():
return 0
def is_fork_support_enabled():
return False
def fork_register_channel(channel):
pass
def fork_unregister_channel(channel):
pass

@ -322,6 +322,7 @@ cdef extern from "grpc/grpc.h":
void grpc_init() nogil
void grpc_shutdown() nogil
int grpc_is_initialized() nogil
ctypedef struct grpc_completion_queue_factory:
pass

@ -127,7 +127,7 @@ class CompressionLevel:
cdef class CallDetails:
def __cinit__(self):
grpc_init()
fork_handlers_and_grpc_init()
with nogil:
grpc_call_details_init(&self.c_details)

@ -20,47 +20,10 @@ import grpc
_LOGGER = logging.getLogger(__name__)
cdef grpc_ssl_certificate_config_reload_status _server_cert_config_fetcher_wrapper(
void* user_data, grpc_ssl_server_certificate_config **config) with gil:
# This is a credentials.ServerCertificateConfig
cdef ServerCertificateConfig cert_config = None
if not user_data:
raise ValueError('internal error: user_data must be specified')
credentials = <ServerCredentials>user_data
if not credentials.initial_cert_config_fetched:
# C-core is asking for the initial cert config
credentials.initial_cert_config_fetched = True
cert_config = credentials.initial_cert_config._certificate_configuration
else:
user_cb = credentials.cert_config_fetcher
try:
cert_config_wrapper = user_cb()
except Exception:
_LOGGER.exception('Error fetching certificate config')
return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL
if cert_config_wrapper is None:
return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED
elif not isinstance(
cert_config_wrapper, grpc.ServerCertificateConfiguration):
_LOGGER.error(
'Error fetching certificate configuration: certificate '
'configuration must be of type grpc.ServerCertificateConfiguration, '
'not %s' % type(cert_config_wrapper).__name__)
return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL
else:
cert_config = cert_config_wrapper._certificate_configuration
config[0] = <grpc_ssl_server_certificate_config*>cert_config.c_cert_config
# our caller will assume ownership of memory, so we have to recreate
# a copy of c_cert_config here
cert_config.c_cert_config = grpc_ssl_server_certificate_config_create(
cert_config.c_pem_root_certs, cert_config.c_ssl_pem_key_cert_pairs,
cert_config.c_ssl_pem_key_cert_pairs_count)
return GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW
cdef class Server:
def __cinit__(self, object arguments):
grpc_init()
fork_handlers_and_grpc_init()
self.references = []
self.registered_completion_queues = []
self._vtable.copy = &_copy_pointer

@ -31,3 +31,6 @@ include "_cygrpc/time.pxd.pxi"
include "_cygrpc/_hooks.pxd.pxi"
include "_cygrpc/grpc_gevent.pxd.pxi"
IF UNAME_SYSNAME != "Windows":
include "_cygrpc/fork_posix.pxd.pxi"

@ -39,6 +39,11 @@ include "_cygrpc/_hooks.pyx.pxi"
include "_cygrpc/grpc_gevent.pyx.pxi"
IF UNAME_SYSNAME == "Windows":
include "_cygrpc/fork_windows.pyx.pxi"
ELSE:
include "_cygrpc/fork_posix.pyx.pxi"
#
# initialize gRPC
#

@ -202,3 +202,28 @@ class RunInterop(test.test):
from tests.interop import client
sys.argv[1:] = self.args.split()
client.test_interoperability()
class RunFork(test.test):
description = 'run fork test client'
user_options = [('args=', 'a', 'pass-thru arguments for the client')]
def initialize_options(self):
self.args = ''
def finalize_options(self):
# distutils requires this override.
pass
def run(self):
if self.distribution.install_requires:
self.distribution.fetch_build_eggs(
self.distribution.install_requires)
if self.distribution.tests_require:
self.distribution.fetch_build_eggs(self.distribution.tests_require)
# We import here to ensure that our setuptools parent has had a chance to
# edit the Python system path.
from tests.fork import client
sys.argv[1:] = self.args.split()
client.test_fork()

@ -52,6 +52,7 @@ COMMAND_CLASS = {
'preprocess': commands.GatherProto,
'build_package_protos': grpc_tools.command.BuildPackageProtos,
'build_py': commands.BuildPy,
'run_fork': commands.RunFork,
'run_interop': commands.RunInterop,
'test_lite': commands.TestLite,
'test_gevent': commands.TestGevent,

@ -0,0 +1,13 @@
# Copyright 2018 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.

@ -0,0 +1,76 @@
# Copyright 2018 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.
"""The Python implementation of the GRPC interoperability test client."""
import argparse
import logging
import sys
from tests.fork import methods
def _args():
def parse_bool(value):
if value == 'true':
return True
if value == 'false':
return False
raise argparse.ArgumentTypeError('Only true/false allowed')
parser = argparse.ArgumentParser()
parser.add_argument(
'--server_host',
default="localhost",
type=str,
help='the host to which to connect')
parser.add_argument(
'--server_port',
type=int,
required=True,
help='the port to which to connect')
parser.add_argument(
'--test_case',
default='large_unary',
type=str,
help='the test case to execute')
parser.add_argument(
'--use_tls',
default=False,
type=parse_bool,
help='require a secure connection')
return parser.parse_args()
def _test_case_from_arg(test_case_arg):
for test_case in methods.TestCase:
if test_case_arg == test_case.value:
return test_case
else:
raise ValueError('No test case "%s"!' % test_case_arg)
def test_fork():
logging.basicConfig(level=logging.INFO)
args = _args()
if args.test_case == "all":
for test_case in methods.TestCase:
test_case.run_test(args)
else:
test_case = _test_case_from_arg(args.test_case)
test_case.run_test(args)
if __name__ == '__main__':
test_fork()

@ -0,0 +1,445 @@
# Copyright 2018 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.
"""Implementations of fork support test methods."""
import enum
import json
import logging
import multiprocessing
import os
import threading
import time
import grpc
from six.moves import queue
from src.proto.grpc.testing import empty_pb2
from src.proto.grpc.testing import messages_pb2
from src.proto.grpc.testing import test_pb2_grpc
_LOGGER = logging.getLogger(__name__)
def _channel(args):
target = '{}:{}'.format(args.server_host, args.server_port)
if args.use_tls:
channel_credentials = grpc.ssl_channel_credentials()
channel = grpc.secure_channel(target, channel_credentials)
else:
channel = grpc.insecure_channel(target)
return channel
def _validate_payload_type_and_length(response, expected_type, expected_length):
if response.payload.type is not expected_type:
raise ValueError('expected payload type %s, got %s' %
(expected_type, type(response.payload.type)))
elif len(response.payload.body) != expected_length:
raise ValueError('expected payload body size %d, got %d' %
(expected_length, len(response.payload.body)))
def _async_unary(stub):
size = 314159
request = messages_pb2.SimpleRequest(
response_type=messages_pb2.COMPRESSABLE,
response_size=size,
payload=messages_pb2.Payload(body=b'\x00' * 271828))
response_future = stub.UnaryCall.future(request)
response = response_future.result()
_validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, size)
def _blocking_unary(stub):
size = 314159
request = messages_pb2.SimpleRequest(
response_type=messages_pb2.COMPRESSABLE,
response_size=size,
payload=messages_pb2.Payload(body=b'\x00' * 271828))
response = stub.UnaryCall(request)
_validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, size)
class _Pipe(object):
def __init__(self):
self._condition = threading.Condition()
self._values = []
self._open = True
def __iter__(self):
return self
def __next__(self):
return self.next()
def next(self):
with self._condition:
while not self._values and self._open:
self._condition.wait()
if self._values:
return self._values.pop(0)
else:
raise StopIteration()
def add(self, value):
with self._condition:
self._values.append(value)
self._condition.notify()
def close(self):
with self._condition:
self._open = False
self._condition.notify()
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
class _ChildProcess(object):
def __init__(self, task, args=None):
if args is None:
args = ()
self._exceptions = multiprocessing.Queue()
def record_exceptions():
try:
task(*args)
except Exception as e: # pylint: disable=broad-except
self._exceptions.put(e)
self._process = multiprocessing.Process(target=record_exceptions)
def start(self):
self._process.start()
def finish(self):
self._process.join()
if self._process.exitcode != 0:
raise ValueError('Child process failed with exitcode %d' %
self._process.exitcode)
try:
exception = self._exceptions.get(block=False)
raise ValueError('Child process failed: %s' % exception)
except queue.Empty:
pass
def _async_unary_same_channel(channel):
def child_target():
try:
_async_unary(stub)
raise Exception(
'Child should not be able to re-use channel after fork')
except ValueError as expected_value_error:
pass
stub = test_pb2_grpc.TestServiceStub(channel)
_async_unary(stub)
child_process = _ChildProcess(child_target)
child_process.start()
_async_unary(stub)
child_process.finish()
def _async_unary_new_channel(channel, args):
def child_target():
child_channel = _channel(args)
child_stub = test_pb2_grpc.TestServiceStub(child_channel)
_async_unary(child_stub)
child_channel.close()
stub = test_pb2_grpc.TestServiceStub(channel)
_async_unary(stub)
child_process = _ChildProcess(child_target)
child_process.start()
_async_unary(stub)
child_process.finish()
def _blocking_unary_same_channel(channel):
def child_target():
try:
_blocking_unary(stub)
raise Exception(
'Child should not be able to re-use channel after fork')
except ValueError as expected_value_error:
pass
stub = test_pb2_grpc.TestServiceStub(channel)
_blocking_unary(stub)
child_process = _ChildProcess(child_target)
child_process.start()
child_process.finish()
def _blocking_unary_new_channel(channel, args):
def child_target():
child_channel = _channel(args)
child_stub = test_pb2_grpc.TestServiceStub(child_channel)
_blocking_unary(child_stub)
child_channel.close()
stub = test_pb2_grpc.TestServiceStub(channel)
_blocking_unary(stub)
child_process = _ChildProcess(child_target)
child_process.start()
_blocking_unary(stub)
child_process.finish()
# Verify that the fork channel registry can handle already closed channels
def _close_channel_before_fork(channel, args):
def child_target():
new_channel.close()
child_channel = _channel(args)
child_stub = test_pb2_grpc.TestServiceStub(child_channel)
_blocking_unary(child_stub)
child_channel.close()
stub = test_pb2_grpc.TestServiceStub(channel)
_blocking_unary(stub)
channel.close()
new_channel = _channel(args)
new_stub = test_pb2_grpc.TestServiceStub(new_channel)
child_process = _ChildProcess(child_target)
child_process.start()
_blocking_unary(new_stub)
child_process.finish()
def _connectivity_watch(channel, args):
def child_target():
def child_connectivity_callback(state):
child_states.append(state)
child_states = []
child_channel = _channel(args)
child_stub = test_pb2_grpc.TestServiceStub(child_channel)
child_channel.subscribe(child_connectivity_callback)
_async_unary(child_stub)
if len(child_states
) < 2 or child_states[-1] != grpc.ChannelConnectivity.READY:
raise ValueError('Channel did not move to READY')
if len(parent_states) > 1:
raise ValueError('Received connectivity updates on parent callback')
child_channel.unsubscribe(child_connectivity_callback)
child_channel.close()
def parent_connectivity_callback(state):
parent_states.append(state)
parent_states = []
channel.subscribe(parent_connectivity_callback)
stub = test_pb2_grpc.TestServiceStub(channel)
child_process = _ChildProcess(child_target)
child_process.start()
_async_unary(stub)
if len(parent_states
) < 2 or parent_states[-1] != grpc.ChannelConnectivity.READY:
raise ValueError('Channel did not move to READY')
channel.unsubscribe(parent_connectivity_callback)
child_process.finish()
# Need to unsubscribe or _channel.py in _poll_connectivity triggers a
# "Cannot invoke RPC on closed channel!" error.
# TODO(ericgribkoff) Fix issue with channel.close() and connectivity polling
channel.unsubscribe(parent_connectivity_callback)
def _ping_pong_with_child_processes_after_first_response(
channel, args, child_target, run_after_close=True):
request_response_sizes = (
31415,
9,
2653,
58979,
)
request_payload_sizes = (
27182,
8,
1828,
45904,
)
stub = test_pb2_grpc.TestServiceStub(channel)
pipe = _Pipe()
parent_bidi_call = stub.FullDuplexCall(pipe)
child_processes = []
first_message_received = False
for response_size, payload_size in zip(request_response_sizes,
request_payload_sizes):
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
response_parameters=(
messages_pb2.ResponseParameters(size=response_size),),
payload=messages_pb2.Payload(body=b'\x00' * payload_size))
pipe.add(request)
if first_message_received:
child_process = _ChildProcess(child_target,
(parent_bidi_call, channel, args))
child_process.start()
child_processes.append(child_process)
response = next(parent_bidi_call)
first_message_received = True
child_process = _ChildProcess(child_target,
(parent_bidi_call, channel, args))
child_process.start()
child_processes.append(child_process)
_validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE,
response_size)
pipe.close()
if run_after_close:
child_process = _ChildProcess(child_target,
(parent_bidi_call, channel, args))
child_process.start()
child_processes.append(child_process)
for child_process in child_processes:
child_process.finish()
def _in_progress_bidi_continue_call(channel):
def child_target(parent_bidi_call, parent_channel, args):
stub = test_pb2_grpc.TestServiceStub(parent_channel)
try:
_async_unary(stub)
raise Exception(
'Child should not be able to re-use channel after fork')
except ValueError as expected_value_error:
pass
inherited_code = parent_bidi_call.code()
inherited_details = parent_bidi_call.details()
if inherited_code != grpc.StatusCode.CANCELLED:
raise ValueError(
'Expected inherited code CANCELLED, got %s' % inherited_code)
if inherited_details != 'Channel closed due to fork':
raise ValueError(
'Expected inherited details Channel closed due to fork, got %s'
% inherited_details)
# Don't run child_target after closing the parent call, as the call may have
# received a status from the server before fork occurs.
_ping_pong_with_child_processes_after_first_response(
channel, None, child_target, run_after_close=False)
def _in_progress_bidi_same_channel_async_call(channel):
def child_target(parent_bidi_call, parent_channel, args):
stub = test_pb2_grpc.TestServiceStub(parent_channel)
try:
_async_unary(stub)
raise Exception(
'Child should not be able to re-use channel after fork')
except ValueError as expected_value_error:
pass
_ping_pong_with_child_processes_after_first_response(
channel, None, child_target)
def _in_progress_bidi_same_channel_blocking_call(channel):
def child_target(parent_bidi_call, parent_channel, args):
stub = test_pb2_grpc.TestServiceStub(parent_channel)
try:
_blocking_unary(stub)
raise Exception(
'Child should not be able to re-use channel after fork')
except ValueError as expected_value_error:
pass
_ping_pong_with_child_processes_after_first_response(
channel, None, child_target)
def _in_progress_bidi_new_channel_async_call(channel, args):
def child_target(parent_bidi_call, parent_channel, args):
channel = _channel(args)
stub = test_pb2_grpc.TestServiceStub(channel)
_async_unary(stub)
_ping_pong_with_child_processes_after_first_response(
channel, args, child_target)
def _in_progress_bidi_new_channel_blocking_call(channel, args):
def child_target(parent_bidi_call, parent_channel, args):
channel = _channel(args)
stub = test_pb2_grpc.TestServiceStub(channel)
_blocking_unary(stub)
_ping_pong_with_child_processes_after_first_response(
channel, args, child_target)
@enum.unique
class TestCase(enum.Enum):
CONNECTIVITY_WATCH = 'connectivity_watch'
CLOSE_CHANNEL_BEFORE_FORK = 'close_channel_before_fork'
ASYNC_UNARY_SAME_CHANNEL = 'async_unary_same_channel'
ASYNC_UNARY_NEW_CHANNEL = 'async_unary_new_channel'
BLOCKING_UNARY_SAME_CHANNEL = 'blocking_unary_same_channel'
BLOCKING_UNARY_NEW_CHANNEL = 'blocking_unary_new_channel'
IN_PROGRESS_BIDI_CONTINUE_CALL = 'in_progress_bidi_continue_call'
IN_PROGRESS_BIDI_SAME_CHANNEL_ASYNC_CALL = 'in_progress_bidi_same_channel_async_call'
IN_PROGRESS_BIDI_SAME_CHANNEL_BLOCKING_CALL = 'in_progress_bidi_same_channel_blocking_call'
IN_PROGRESS_BIDI_NEW_CHANNEL_ASYNC_CALL = 'in_progress_bidi_new_channel_async_call'
IN_PROGRESS_BIDI_NEW_CHANNEL_BLOCKING_CALL = 'in_progress_bidi_new_channel_blocking_call'
def run_test(self, args):
_LOGGER.info("Running %s", self)
channel = _channel(args)
if self is TestCase.ASYNC_UNARY_SAME_CHANNEL:
_async_unary_same_channel(channel)
elif self is TestCase.ASYNC_UNARY_NEW_CHANNEL:
_async_unary_new_channel(channel, args)
elif self is TestCase.BLOCKING_UNARY_SAME_CHANNEL:
_blocking_unary_same_channel(channel)
elif self is TestCase.BLOCKING_UNARY_NEW_CHANNEL:
_blocking_unary_new_channel(channel, args)
elif self is TestCase.CLOSE_CHANNEL_BEFORE_FORK:
_close_channel_before_fork(channel, args)
elif self is TestCase.CONNECTIVITY_WATCH:
_connectivity_watch(channel, args)
elif self is TestCase.IN_PROGRESS_BIDI_CONTINUE_CALL:
_in_progress_bidi_continue_call(channel)
elif self is TestCase.IN_PROGRESS_BIDI_SAME_CHANNEL_ASYNC_CALL:
_in_progress_bidi_same_channel_async_call(channel)
elif self is TestCase.IN_PROGRESS_BIDI_SAME_CHANNEL_BLOCKING_CALL:
_in_progress_bidi_same_channel_blocking_call(channel)
elif self is TestCase.IN_PROGRESS_BIDI_NEW_CHANNEL_ASYNC_CALL:
_in_progress_bidi_new_channel_async_call(channel, args)
elif self is TestCase.IN_PROGRESS_BIDI_NEW_CHANNEL_BLOCKING_CALL:
_in_progress_bidi_new_channel_blocking_call(channel, args)
else:
raise NotImplementedError(
'Test case "%s" not implemented!' % self.name)
channel.close()

@ -53,5 +53,5 @@ class TestRunner(threading.Thread):
except Exception as e: # pylint: disable=broad-except
traceback.print_exc()
self._exception_queue.put(
Exception("An exception occured during test {}"
Exception("An exception occurred during test {}"
.format(test_case), e))

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

Loading…
Cancel
Save