diff options
author | Nicolas Noble <nicolasnoble@users.noreply.github.com> | 2016-05-09 23:18:34 -0700 |
---|---|---|
committer | Nicolas Noble <nicolasnoble@users.noreply.github.com> | 2016-05-09 23:18:34 -0700 |
commit | fac1b4d220bc0c06b997503d550889dfbea3a14c (patch) | |
tree | e23c88785f97a3ed0bf3db943cf2bc3e7564790b | |
parent | b98e24b32b708c929cf14ea13f5fc94234a56995 (diff) | |
parent | 6915e6b96f607d01e674dbb22855b84bc7b2bfc1 (diff) |
Merge pull request #6475 from grpc/release-0_14
Upmerge from 0.14.0
33 files changed, 498 insertions, 375 deletions
diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 1229d488ed..d2d9ac7808 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -114,6 +114,38 @@ #define GPR_WIN32_ATOMIC 1 #define GPR_MSVC_TLS 1 #endif +#elif defined(GPR_MANYLINUX1) +// TODO(atash): manylinux1 is just another __linux__ but with ancient +// libraries; it should be integrated with the `__linux__` definitions below. +#define GPR_PLATFORM_STRING "manylinux" +#define GPR_POSIX_CRASH_HANDLER 1 +#define GPR_CPU_LINUX 1 +#define GPR_GCC_ATOMIC 1 +#define GPR_GCC_TLS 1 +#define GPR_LINUX 1 +#define GPR_LINUX_LOG 1 +#define GPR_POSIX_SOCKET 1 +#define GPR_POSIX_WAKEUP_FD 1 +#define GPR_POSIX_SOCKETADDR 1 +#define GPR_POSIX_NO_SPECIAL_WAKEUP_FD 1 +#define GPR_POSIX_SOCKETUTILS 1 +#define GPR_HAVE_UNIX_SOCKET 1 +#define GPR_HAVE_IP_PKTINFO 1 +#define GPR_HAVE_IPV6_RECVPKTINFO 1 +#define GPR_LINUX_ENV 1 +#define GPR_POSIX_FILE 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 +#define GPR_HAVE_MSG_NOSIGNAL 1 +#ifdef _LP64 +#define GPR_ARCH_64 1 +#else /* _LP64 */ +#define GPR_ARCH_32 1 +#endif /* _LP64 */ #elif defined(ANDROID) || defined(__ANDROID__) #define GPR_PLATFORM_STRING "android" #define GPR_ANDROID 1 @@ -54,7 +54,6 @@ sys.path.insert(0, os.path.abspath(PYTHON_STEM)) # Break import-style to ensure we can actually find our in-repo dependencies. import commands -import precompiled import grpc_core_dependencies import grpc_version @@ -173,7 +172,6 @@ COMMAND_CLASS = { 'build_project_metadata': commands.BuildProjectMetadata, 'build_py': commands.BuildPy, 'build_ext': commands.BuildExt, - 'build_tagged_ext': precompiled.BuildTaggedExt, 'gather': commands.Gather, 'run_interop': commands.RunInterop, 'test_lite': commands.TestLite @@ -229,25 +227,21 @@ else: PACKAGES = setuptools.find_packages( PYTHON_STEM, exclude=['tests', 'tests.*']) -setup_arguments = { - 'name': 'grpcio', - 'version': grpc_version.VERSION, - 'license': LICENSE, - 'ext_modules': CYTHON_EXTENSION_MODULES, - 'packages': list(PACKAGES), - 'package_dir': PACKAGE_DIRECTORIES, - # TODO(atash): Figure out why auditwheel doesn't like namespace packages. - #'namespace_packages': ['grpc'], - 'package_data': PACKAGE_DATA, - 'install_requires': INSTALL_REQUIRES, - 'setup_requires': SETUP_REQUIRES, - 'cmdclass': COMMAND_CLASS, - 'tests_require': TESTS_REQUIRE, - 'test_suite': TEST_SUITE, - 'test_loader': TEST_LOADER, - 'test_runner': TEST_RUNNER, -} - -precompiled.update_setup_arguments(setup_arguments) - -setuptools.setup(**setup_arguments) +setuptools.setup( + name='grpcio', + version=grpc_version.VERSION, + license=LICENSE, + ext_modules=CYTHON_EXTENSION_MODULES, + packages=list(PACKAGES), + package_dir=PACKAGE_DIRECTORIES, + # TODO(atash): Figure out why auditwheel doesn't like namespace packages. + #namespace_packages=['grpc'], + package_data=PACKAGE_DATA, + install_requires=INSTALL_REQUIRES, + setup_requires=SETUP_REQUIRES, + cmdclass=COMMAND_CLASS, + tests_require=TESTS_REQUIRE, + test_suite=TEST_SUITE, + test_loader=TEST_LOADER, + test_runner=TEST_RUNNER, +) diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index ac0fee1ec4..29c359c539 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -214,10 +214,10 @@ std::string GetMethodReturnTypeServer(const MethodDescriptor *method) { switch (GetMethodType(method)) { case METHODTYPE_NO_STREAMING: case METHODTYPE_CLIENT_STREAMING: - return "Task<" + GetClassName(method->output_type()) + ">"; + return "global::System.Threading.Tasks.Task<" + GetClassName(method->output_type()) + ">"; case METHODTYPE_SERVER_STREAMING: case METHODTYPE_BIDI_STREAMING: - return "Task"; + return "global::System.Threading.Tasks.Task"; } GOOGLE_LOG(FATAL)<< "Can't get here."; return ""; diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 2d3034d28b..d700a18778 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -151,25 +151,25 @@ namespace Math { /// Div divides args.dividend by args.divisor and returns the quotient and /// remainder. /// </summary> - Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context); /// <summary> /// DivMany accepts an arbitrary number of division args from the client stream /// and sends back the results in the reply stream. The stream continues until /// the client closes its end; the server does the same after sending all the /// replies. The stream ends immediately if either end aborts. /// </summary> - Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context); /// <summary> /// Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib /// generates up to limit numbers; otherwise it continues until the call is /// canceled. Unlike Fib above, Fib has no final FibReply. /// </summary> - Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context); /// <summary> /// Sum sums a stream of numbers, returning the final result once the stream /// is closed. /// </summary> - Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context); } /// <summary>Base class for server-side implementations of Math</summary> @@ -179,7 +179,7 @@ namespace Math { /// Div divides args.dividend by args.divisor and returns the quotient and /// remainder. /// </summary> - public virtual Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -190,7 +190,7 @@ namespace Math { /// the client closes its end; the server does the same after sending all the /// replies. The stream ends immediately if either end aborts. /// </summary> - public virtual Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -200,7 +200,7 @@ namespace Math { /// generates up to limit numbers; otherwise it continues until the call is /// canceled. Unlike Fib above, Fib has no final FibReply. /// </summary> - public virtual Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -209,7 +209,7 @@ namespace Math { /// Sum sums a stream of numbers, returning the final result once the stream /// is closed. /// </summary> - public virtual Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 967d1170be..51c6a39b1d 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -72,13 +72,13 @@ namespace Grpc.Health.V1 { [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IHealth { - Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context); } /// <summary>Base class for server-side implementations of Health</summary> public abstract class HealthBase { - public virtual Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs index aa4f1c5c3e..9d31d1c514 100644 --- a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs @@ -112,11 +112,11 @@ namespace Grpc.Testing { /// Returns the values of all the gauges that are currently being maintained by /// the service /// </summary> - Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context); /// <summary> /// Returns the value of one gauge /// </summary> - Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context); } /// <summary>Base class for server-side implementations of MetricsService</summary> @@ -126,7 +126,7 @@ namespace Grpc.Testing { /// Returns the values of all the gauges that are currently being maintained by /// the service /// </summary> - public virtual Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -134,7 +134,7 @@ namespace Grpc.Testing { /// <summary> /// Returns the value of one gauge /// </summary> - public virtual Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs index 42bf5e0b58..f7071ebf6b 100644 --- a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs @@ -111,12 +111,12 @@ namespace Grpc.Testing { /// One request followed by one response. /// The server returns the client payload as-is. /// </summary> - Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); /// <summary> /// One request followed by one response. /// The server returns the client payload as-is. /// </summary> - Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context); } /// <summary>Base class for server-side implementations of BenchmarkService</summary> @@ -126,7 +126,7 @@ namespace Grpc.Testing { /// One request followed by one response. /// The server returns the client payload as-is. /// </summary> - public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -135,7 +135,7 @@ namespace Grpc.Testing { /// One request followed by one response. /// The server returns the client payload as-is. /// </summary> - public virtual Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -375,7 +375,7 @@ namespace Grpc.Testing { /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// </summary> - Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context); /// <summary> /// Start client with specified workload. /// First request sent specifies the ClientConfig followed by ClientStatus @@ -384,15 +384,15 @@ namespace Grpc.Testing { /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// </summary> - Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context); /// <summary> /// Just return the core count - unary call /// </summary> - Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context); /// <summary> /// Quit this worker /// </summary> - Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context); } /// <summary>Base class for server-side implementations of WorkerService</summary> @@ -406,7 +406,7 @@ namespace Grpc.Testing { /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// </summary> - public virtual Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -419,7 +419,7 @@ namespace Grpc.Testing { /// and once the shutdown has finished, the OK status is sent to terminate /// this RPC. /// </summary> - public virtual Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -427,7 +427,7 @@ namespace Grpc.Testing { /// <summary> /// Just return the core count - unary call /// </summary> - public virtual Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -435,7 +435,7 @@ namespace Grpc.Testing { /// <summary> /// Quit this worker /// </summary> - public virtual Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index f1878cbb55..cf43a77118 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -196,34 +196,34 @@ namespace Grpc.Testing { /// <summary> /// One empty request followed by one empty response. /// </summary> - Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context); /// <summary> /// One request followed by one response. /// </summary> - Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); /// <summary> /// One request followed by a sequence of responses (streamed download). /// The server returns the payload with client desired type and sizes. /// </summary> - Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); /// <summary> /// A sequence of requests followed by one response (streamed upload). /// The server returns the aggregated size of client payload as the result. /// </summary> - Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context); /// <summary> /// A sequence of requests with each request served by the server immediately. /// As one request could lead to multiple responses, this interface /// demonstrates the idea of full duplexing. /// </summary> - Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); /// <summary> /// A sequence of requests followed by a sequence of responses. /// The server buffers all the client requests and then serves them in order. A /// stream of responses are returned to the client when the server starts with /// first request. /// </summary> - Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); + global::System.Threading.Tasks.Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); } /// <summary>Base class for server-side implementations of TestService</summary> @@ -232,7 +232,7 @@ namespace Grpc.Testing { /// <summary> /// One empty request followed by one empty response. /// </summary> - public virtual Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -240,7 +240,7 @@ namespace Grpc.Testing { /// <summary> /// One request followed by one response. /// </summary> - public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -249,7 +249,7 @@ namespace Grpc.Testing { /// One request followed by a sequence of responses (streamed download). /// The server returns the payload with client desired type and sizes. /// </summary> - public virtual Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -258,7 +258,7 @@ namespace Grpc.Testing { /// A sequence of requests followed by one response (streamed upload). /// The server returns the aggregated size of client payload as the result. /// </summary> - public virtual Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -268,7 +268,7 @@ namespace Grpc.Testing { /// As one request could lead to multiple responses, this interface /// demonstrates the idea of full duplexing. /// </summary> - public virtual Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -279,7 +279,7 @@ namespace Grpc.Testing { /// stream of responses are returned to the client when the server starts with /// first request. /// </summary> - public virtual Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -525,7 +525,7 @@ namespace Grpc.Testing { /// <summary> /// A call that no server should implement /// </summary> - Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context); } /// <summary>Base class for server-side implementations of UnimplementedService</summary> @@ -534,7 +534,7 @@ namespace Grpc.Testing { /// <summary> /// A call that no server should implement /// </summary> - public virtual Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } @@ -669,19 +669,19 @@ namespace Grpc.Testing { [System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")] public interface IReconnectService { - Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context); - Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context); + global::System.Threading.Tasks.Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context); } /// <summary>Base class for server-side implementations of ReconnectService</summary> public abstract class ReconnectServiceBase { - public virtual Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.ReconnectParams request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } - public virtual Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context) + public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context) { throw new RpcException(new Status(StatusCode.Unimplemented, "")); } diff --git a/src/python/grpcio/precompiled.py b/src/python/grpcio/precompiled.py deleted file mode 100644 index b6aa7fc90e..0000000000 --- a/src/python/grpcio/precompiled.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import os -import platform -import shutil -import sys -import sysconfig - -import setuptools - -import commands -import grpc_version - -try: - from urllib2 import urlopen -except ImportError: - from urllib.request import urlopen - -PYTHON_STEM = os.path.dirname(os.path.abspath(__file__)) -BINARIES_REPOSITORY = os.environ.get( - 'GRPC_PYTHON_BINARIES_REPOSITORY', - 'https://storage.googleapis.com/grpc-precompiled-binaries/python') -USE_PRECOMPILED_BINARIES = bool(int(os.environ.get( - 'GRPC_PYTHON_USE_PRECOMPILED_BINARIES', '1'))) - -def _tagged_ext_name(base): - uname = platform.uname() - tags = ( - grpc_version.VERSION, - 'py{}'.format(sysconfig.get_python_version()), - uname[0], - uname[4], - ) - ucs = 'ucs{}'.format(sysconfig.get_config_var('Py_UNICODE_SIZE')) - return '{base}-{tags}-{ucs}'.format( - base=base, tags='-'.join(tags), ucs=ucs) - - -class BuildTaggedExt(setuptools.Command): - - description = 'build the gRPC tagged extensions' - user_options = [] - - def initialize_options(self): - # distutils requires this override. - pass - - def finalize_options(self): - # distutils requires this override. - pass - - def run(self): - if 'linux' in sys.platform: - self.run_command('build_ext') - try: - os.makedirs('dist/') - except OSError: - pass - shutil.copyfile( - os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so'), - 'dist/{}.so'.format(_tagged_ext_name('cygrpc'))) - else: - sys.stderr.write('nothing to do for build_tagged_ext\n') - - -def update_setup_arguments(setup_arguments): - if not USE_PRECOMPILED_BINARIES: - sys.stderr.write('not using precompiled extension') - return - url = '{}/{}.so'.format(BINARIES_REPOSITORY, _tagged_ext_name('cygrpc')) - target_path = os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so') - try: - extension = urlopen(url).read() - except: - sys.stderr.write( - 'could not download precompiled extension: {}\n'.format(url)) - return - try: - with open(target_path, 'w') as target: - target.write(extension) - setup_arguments['ext_modules'] = [] - except: - sys.stderr.write( - 'could not write precompiled extension to directory: {} -> {}\n' - .format(url, target_path)) - return - setup_arguments['package_data']['grpc._cython'].append('cygrpc.so') diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c index 06a07ac646..5277148fc9 100644 --- a/src/ruby/ext/grpc/rb_grpc.c +++ b/src/ruby/ext/grpc/rb_grpc.c @@ -50,6 +50,7 @@ #include "rb_loader.h" #include "rb_server.h" #include "rb_server_credentials.h" +#include "rb_signal.h" static VALUE grpc_rb_cTimeVal = Qnil; @@ -332,6 +333,7 @@ void Init_grpc_c() { Init_grpc_channel_credentials(); Init_grpc_server(); Init_grpc_server_credentials(); + Init_grpc_signals(); Init_grpc_status_codes(); Init_grpc_time_consts(); } diff --git a/src/ruby/ext/grpc/rb_signal.c b/src/ruby/ext/grpc/rb_signal.c new file mode 100644 index 0000000000..a9e512374b --- /dev/null +++ b/src/ruby/ext/grpc/rb_signal.c @@ -0,0 +1,70 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <ruby/ruby.h> +#include <signal.h> +#include <stdbool.h> + +#include <grpc/support/log.h> + +#include "rb_grpc.h" + +static void (*old_sigint_handler)(int); +static void (*old_sigterm_handler)(int); + +static volatile bool signal_received = false; + +/* This has to be handled at the C level instead of Ruby, because Ruby signal + * handlers are constrained to run in the main interpreter thread. If that main + * thread is blocked on grpc_completion_queue_pluck, the signal handlers will + * never run */ +static void handle_signal(int signum) { + signal_received = true; + if (signum == SIGINT) { + old_sigint_handler(signum); + } else if (signum == SIGTERM) { + old_sigterm_handler(signum); + } +} + +static VALUE grpc_rb_signal_received(VALUE self) { + (void)self; + return signal_received ? Qtrue : Qfalse; +} + +void Init_grpc_signals() { + old_sigint_handler = signal(SIGINT, handle_signal); + old_sigterm_handler = signal(SIGTERM, handle_signal); + rb_define_singleton_method(grpc_rb_mGrpcCore, "signal_received?", + grpc_rb_signal_received, 0); +} diff --git a/src/ruby/ext/grpc/rb_signal.h b/src/ruby/ext/grpc/rb_signal.h new file mode 100644 index 0000000000..07e49c0a8b --- /dev/null +++ b/src/ruby/ext/grpc/rb_signal.h @@ -0,0 +1,39 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_RB_SIGNAL_H_ +#define GRPC_RB_SIGNAL_H_ + +void Init_grpc_signals(); + +#endif /* GRPC_RB_SIGNAL_H_ */ diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb index 79fa705b1c..7c9aae30e9 100644 --- a/src/ruby/lib/grpc.rb +++ b/src/ruby/lib/grpc.rb @@ -33,6 +33,7 @@ require_relative 'grpc/errors' require_relative 'grpc/grpc' require_relative 'grpc/logconfig' require_relative 'grpc/notifier' +require_relative 'grpc/signals' require_relative 'grpc/version' require_relative 'grpc/core/time_consts' require_relative 'grpc/generic/active_call' @@ -47,3 +48,5 @@ begin ensure file.close end + +GRPC::Signals.wait_for_signals diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb index ecf3cc3293..fd20a86144 100644 --- a/src/ruby/lib/grpc/generic/active_call.rb +++ b/src/ruby/lib/grpc/generic/active_call.rb @@ -28,7 +28,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 'forwardable' +require 'weakref' require_relative 'bidi_call' +require_relative '../signals' class Struct # BatchResult is the struct returned by calls to call#start_batch. @@ -121,6 +123,10 @@ module GRPC @unmarshal = unmarshal @metadata_tag = metadata_tag @op_notifier = nil + weak_self = WeakRef.new(self) + remove_handler = GRPC::Signals.register_handler(&weak_self + .method(:cancel)) + ObjectSpace.define_finalizer(self, remove_handler) end # output_metadata are provides access to hash that can be used to diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index a0f4071adc..238aaa9656 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -28,46 +28,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require_relative '../grpc' +require_relative '../signals' require_relative 'active_call' require_relative 'service' require 'thread' -# A global that contains signals the gRPC servers should respond to. -$grpc_signals = [] - # GRPC contains the General RPC module. module GRPC - # Handles the signals in $grpc_signals. - # - # @return false if the server should exit, true if not. - def handle_signals - loop do - sig = $grpc_signals.shift - case sig - when 'INT' - return false - when 'TERM' - return false - when nil - return true - end - end - true - end - module_function :handle_signals - - # Sets up a signal handler that adds signals to the signal handling global. - # - # Signal handlers should do as little as humanly possible. - # Here, they just add themselves to $grpc_signals - # - # RpcServer (and later other parts of gRPC) monitors the signals - # $grpc_signals in its own non-signal context. - def trap_signals - %w(INT TERM).each { |sig| trap(sig) { $grpc_signals << sig } } - end - module_function :trap_signals - # Pool is a simple thread pool. class Pool # Default keep alive period is 1s @@ -328,23 +295,6 @@ module GRPC end end - # Runs the server in its own thread, then waits for signal INT or TERM on - # the current thread to terminate it. - def run_till_terminated - GRPC.trap_signals - t = Thread.new do - run - end - t.abort_on_exception = true - wait_till_running - until running_state == :stopped - sleep SIGNAL_CHECK_PERIOD - break unless GRPC.handle_signals - end - stop - t.join - end - # handle registration of classes # # service is either a class that includes GRPC::GenericService and whose @@ -403,9 +353,14 @@ module GRPC transition_running_state(:running) @run_cond.broadcast end + remove_signal_handler = GRPC::Signals.register_handler { stop } loop_handle_server_calls + # Remove signal handler when server stops + remove_signal_handler.call end + alias_method :run_till_terminated, :run + # Sends RESOURCE_EXHAUSTED if there are too many unprocessed jobs def available?(an_rpc) jobs_count, max = @pool.jobs_waiting, @max_waiting_requests @@ -503,10 +458,8 @@ module GRPC unless cls.include?(GenericService) fail "#{cls} must 'include GenericService'" end - if cls.rpc_descs.size.zero? - fail "#{cls} should specify some rpc descriptions" - end - cls.assert_rpc_descs_have_methods + fail "#{cls} should specify some rpc descriptions" if + cls.rpc_descs.size.zero? end # This should be called while holding @run_mutex diff --git a/src/ruby/lib/grpc/generic/service.rb b/src/ruby/lib/grpc/generic/service.rb index 8e940b5b13..0a166e823e 100644 --- a/src/ruby/lib/grpc/generic/service.rb +++ b/src/ruby/lib/grpc/generic/service.rb @@ -110,6 +110,9 @@ module GRPC rpc_descs[name] = RpcDesc.new(name, input, output, marshal_class_method, unmarshal_class_method) + define_method(name) do + fail GRPC::BadStatus, GRPC::Core::StatusCodes::UNIMPLEMENTED + end end def inherited(subclass) @@ -199,19 +202,6 @@ module GRPC end end end - - # Asserts that the appropriate methods are defined for each added rpc - # spec. Is intended to aid verifying that server classes are correctly - # implemented. - def assert_rpc_descs_have_methods - rpc_descs.each_pair do |m, spec| - mth_name = GenericService.underscore(m.to_s).to_sym - unless instance_methods.include?(mth_name) - fail "#{self} does not provide instance method '#{mth_name}'" - end - spec.assert_arity_matches(instance_method(mth_name)) - end - end end def self.included(o) diff --git a/src/ruby/lib/grpc/signals.rb b/src/ruby/lib/grpc/signals.rb new file mode 100644 index 0000000000..2ab85c8bb1 --- /dev/null +++ b/src/ruby/lib/grpc/signals.rb @@ -0,0 +1,69 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +require 'thread' +require_relative 'grpc' + +# GRPC contains the General RPC module. +module GRPC + # Signals contains gRPC functions related to signal handling + module Signals + @interpreter_exiting = false + @signal_handlers = [] + @handlers_mutex = Mutex.new + + def register_handler(&handler) + @handlers_mutex.synchronize do + @signal_handlers.push(handler) + handler.call if @exit_signal_received + end + # Returns a function to remove the handler + lambda do + @handlers_mutex.synchronize { @signal_handlers.delete(handler) } + end + end + module_function :register_handler + + def wait_for_signals + t = Thread.new do + sleep 0.1 until GRPC::Core.signal_received? || @interpreter_exiting + unless @interpreter_exiting + @handlers_mutex.synchronize do + @signal_handlers.each(&:call) + end + end + end + at_exit do + @interpreter_exiting = true + t.join + end + end + module_function :wait_for_signals + end +end diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb index e688057cb1..2a42736237 100644 --- a/src/ruby/spec/generic/rpc_server_spec.rb +++ b/src/ruby/spec/generic/rpc_server_spec.rb @@ -308,10 +308,6 @@ describe GRPC::RpcServer do expect { @srv.handle(EmptyService) }.to raise_error end - it 'raises if the service does not define its rpc methods' do - expect { @srv.handle(NoRpcImplementation) }.to raise_error - end - it 'raises if a handler method is already registered' do @srv.handle(EchoService) expect { r.handle(EchoService) }.to raise_error @@ -349,6 +345,25 @@ describe GRPC::RpcServer do t.join end + it 'should return UNIMPLEMENTED on unimplemented methods', server: true do + @srv.handle(NoRpcImplementation) + t = Thread.new { @srv.run } + @srv.wait_till_running + req = EchoMsg.new + blk = proc do + cq = GRPC::Core::CompletionQueue.new + stub = GRPC::ClientStub.new(@host, cq, :this_channel_is_insecure, + **client_opts) + stub.request_response('/an_rpc', req, marshal, unmarshal) + end + expect(&blk).to raise_error do |error| + expect(error).to be_a(GRPC::BadStatus) + expect(error.code).to be(GRPC::Core::StatusCodes::UNIMPLEMENTED) + end + @srv.stop + t.join + end + it 'should handle multiple sequential requests', server: true do @srv.handle(EchoService) t = Thread.new { @srv.run } diff --git a/src/ruby/spec/generic/service_spec.rb b/src/ruby/spec/generic/service_spec.rb index 5e7b6c7aba..76034e4f74 100644 --- a/src/ruby/spec/generic/service_spec.rb +++ b/src/ruby/spec/generic/service_spec.rb @@ -273,73 +273,4 @@ describe GenericService do end end end - - describe '#assert_rpc_descs_have_methods' do - it 'fails if there is no instance method for an rpc descriptor' do - c1 = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - end - expect { c1.assert_rpc_descs_have_methods }.to raise_error - - c2 = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - rpc :AnotherRpc, GoodMsg, GoodMsg - - def an_rpc - end - end - expect { c2.assert_rpc_descs_have_methods }.to raise_error - end - - it 'passes if there are corresponding methods for each descriptor' do - c = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - rpc :AServerStreamer, GoodMsg, stream(GoodMsg) - rpc :AClientStreamer, stream(GoodMsg), GoodMsg - rpc :ABidiStreamer, stream(GoodMsg), stream(GoodMsg) - - def an_rpc(_req, _call) - end - - def a_server_streamer(_req, _call) - end - - def a_client_streamer(_call) - end - - def a_bidi_streamer(_call) - end - end - expect { c.assert_rpc_descs_have_methods }.to_not raise_error - end - - it 'passes for subclasses of that include GenericService' do - base = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - - def an_rpc(_req, _call) - end - end - c = Class.new(base) - expect { c.assert_rpc_descs_have_methods }.to_not raise_error - expect(c.include?(GenericService)).to be(true) - end - - it 'passes if subclasses define the rpc methods' do - base = Class.new do - include GenericService - rpc :AnRpc, GoodMsg, GoodMsg - end - c = Class.new(base) do - def an_rpc(_req, _call) - end - end - expect { c.assert_rpc_descs_have_methods }.to_not raise_error - expect(c.include?(GenericService)).to be(true) - end - end end diff --git a/test/distrib/python/run_distrib_test.sh b/test/distrib/python/run_distrib_test.sh index 6196e540c8..8a983bc248 100755 --- a/test/distrib/python/run_distrib_test.sh +++ b/test/distrib/python/run_distrib_test.sh @@ -48,7 +48,10 @@ which $PYTHON || PYTHON=python which $PIP || PIP=pip # TODO(jtattermusch): this shouldn't be required -${PIP} install --upgrade six pip +# TODO(jtattermusch): run the command twice to workaround docker-on-overlay +# issue https://github.com/docker/docker/issues/12327 +# (first attempt will fail when using docker with overlayFS) +${PIP} install --upgrade six pip || ${PIP} install --upgrade six pip # At least one of the bdist packages has to succeed (whichever one matches the # test machine, anyway). @@ -58,6 +61,6 @@ done # TODO(jtattermusch): add a .proto file to the distribtest, generate python # code from it and then use the generated code from distribtest.py -$PYTHON -m grpc.protoc.compiler +$PYTHON -m grpc.tools.protoc $PYTHON distribtest.py diff --git a/tools/distrib/python/grpcio_tools/MANIFEST.in b/tools/distrib/python/grpcio_tools/MANIFEST.in index e6ab312f09..7712834d64 100644 --- a/tools/distrib/python/grpcio_tools/MANIFEST.in +++ b/tools/distrib/python/grpcio_tools/MANIFEST.in @@ -1,5 +1,7 @@ +include grpc_version.py include protoc_deps.py include protoc_lib_deps.py +include README.rst graft grpc graft grpc_root graft third_party diff --git a/tools/distrib/python/grpcio_tools/README.rst b/tools/distrib/python/grpcio_tools/README.rst new file mode 100644 index 0000000000..10d2fe8c30 --- /dev/null +++ b/tools/distrib/python/grpcio_tools/README.rst @@ -0,0 +1,128 @@ +gRPC Python Tools +================= + +Package for gRPC Python tools. + +Installation +------------ + +The gRPC Python tools package is available for Linux, Mac OS X, and Windows +running Python 2.7. + +From PyPI +~~~~~~~~~ + +If you are installing locally... + +:: + + $ pip install grpcio-tools + +Else system wide (on Ubuntu)... + +:: + + $ sudo pip install grpcio-tools + +If you're on Windows make sure that you installed the :code:`pip.exe` component +when you installed Python (if not go back and install it!) then invoke: + +:: + + $ pip.exe install grpcio-tools + +Windows users may need to invoke :code:`pip.exe` from a command line ran as +administrator. + +n.b. On Windows and on Mac OS X one *must* have a recent release of :code:`pip` +to retrieve the proper wheel from PyPI. Be sure to upgrade to the latest +version! + +You might also need to install Cython to handle installation via the source +distribution if gRPC Python's system coverage with wheels does not happen to +include your system. + +From Source +~~~~~~~~~~~ + +Building from source requires that you have the Python headers (usually a +package named :code:`python-dev`) and Cython installed. It further requires a +GCC-like compiler to go smoothly; you can probably get it to work without +GCC-like stuff, but you may end up having a bad time. + +:: + + $ export REPO_ROOT=grpc # REPO_ROOT can be any directory of your choice + $ git clone https://github.com/grpc/grpc.git $REPO_ROOT + $ cd $REPO_ROOT + $ git submodule update --init + + $ cd tools/distrib/python/grpcio_tools + $ python ../make_grpcio_tools.py + + # For the next command do `sudo pip install` if you get permission-denied errors + $ pip install . + +You cannot currently install Python from source on Windows. Things might work +out for you in MSYS2 (follow the Linux instructions), but it isn't officially +supported at the moment. + +Troubleshooting +~~~~~~~~~~~~~~~ + +Help, I ... + +* **... see a** :code:`pkg_resources.VersionConflict` **when I try to install + grpc** + + This is likely because :code:`pip` doesn't own the offending dependency, + which in turn is likely because your operating system's package manager owns + it. You'll need to force the installation of the dependency: + + :code:`pip install --ignore-installed $OFFENDING_DEPENDENCY` + + For example, if you get an error like the following: + + :: + + Traceback (most recent call last): + File "<string>", line 17, in <module> + ... + File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 509, in find + raise VersionConflict(dist, req) + pkg_resources.VersionConflict: (six 1.8.0 (/usr/lib/python2.7/dist-packages), Requirement.parse('six>=1.10')) + + You can fix it by doing: + + :: + + sudo pip install --ignore-installed six + +* **... see compiler errors on some platforms when either installing from source or from the source distribution** + + If you see + + :: + + /tmp/pip-build-U8pSsr/cython/Cython/Plex/Scanners.c:4:20: fatal error: Python.h: No such file or directory + #include "Python.h" + ^ + compilation terminated. + + You can fix it by installing `python-dev` package. i.e + + :: + + sudo apt-get install python-dev + + If you see something similar to: + + :: + + third_party/protobuf/src/google/protobuf/stubs/mathlimits.h:173:31: note: in expansion of macro 'SIGNED_INT_MAX' + static const Type kPosMax = SIGNED_INT_MAX(Type); \\ + ^ + And your toolchain is GCC (at the time of this writing, up through at least + GCC 6.0), this is probably a bug where GCC chokes on constant expressions + when the :code:`-fwrapv` flag is specified. You should consider setting your + environment with :code:`CFLAGS=-fno-wrapv` or using clang (:code:`CC=clang`). diff --git a/tools/distrib/python/grpcio_tools/grpc/protoc/__init__.py b/tools/distrib/python/grpcio_tools/grpc/tools/__init__.py index d5ad73a74a..d5ad73a74a 100644 --- a/tools/distrib/python/grpcio_tools/grpc/protoc/__init__.py +++ b/tools/distrib/python/grpcio_tools/grpc/tools/__init__.py diff --git a/tools/distrib/python/grpcio_tools/grpc/protoc/main.cc b/tools/distrib/python/grpcio_tools/grpc/tools/main.cc index c9936a3a6b..81675b4e6f 100644 --- a/tools/distrib/python/grpcio_tools/grpc/protoc/main.cc +++ b/tools/distrib/python/grpcio_tools/grpc/tools/main.cc @@ -32,7 +32,7 @@ #include "src/compiler/python_generator.h" -#include "grpc/protoc/main.h" +#include "grpc/tools/main.h" int protoc_main(int argc, char* argv[]) { google::protobuf::compiler::CommandLineInterface cli; diff --git a/tools/distrib/python/grpcio_tools/grpc/protoc/main.h b/tools/distrib/python/grpcio_tools/grpc/tools/main.h index ea2860ff02..ea2860ff02 100644 --- a/tools/distrib/python/grpcio_tools/grpc/protoc/main.h +++ b/tools/distrib/python/grpcio_tools/grpc/tools/main.h diff --git a/tools/distrib/python/grpcio_tools/grpc/protoc/compiler.py b/tools/distrib/python/grpcio_tools/grpc/tools/protoc.py index caafc544b2..b4dd0ecae2 100644 --- a/tools/distrib/python/grpcio_tools/grpc/protoc/compiler.py +++ b/tools/distrib/python/grpcio_tools/grpc/tools/protoc.py @@ -31,7 +31,7 @@ import sys -from grpc.protoc import protoc_compiler +from grpc.tools import protoc_compiler if __name__ == '__main__': diff --git a/tools/distrib/python/grpcio_tools/grpc/protoc/protoc_compiler.pyx b/tools/distrib/python/grpcio_tools/grpc/tools/protoc_compiler.pyx index af15f3db30..a6530127c0 100644 --- a/tools/distrib/python/grpcio_tools/grpc/protoc/protoc_compiler.pyx +++ b/tools/distrib/python/grpcio_tools/grpc/tools/protoc_compiler.pyx @@ -29,7 +29,7 @@ from libc cimport stdlib -cdef extern from "grpc/protoc/main.h": +cdef extern from "grpc/tools/main.h": int protoc_main(int argc, char *argv[]) def run_main(list args not None): diff --git a/tools/distrib/python/grpcio_tools/setup.py b/tools/distrib/python/grpcio_tools/setup.py index 0281c01796..576f7ae32a 100644 --- a/tools/distrib/python/grpcio_tools/setup.py +++ b/tools/distrib/python/grpcio_tools/setup.py @@ -30,6 +30,7 @@ from distutils import extension import os import os.path +import shlex import sys import setuptools @@ -40,18 +41,28 @@ from setuptools.command import build_ext os.chdir(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, os.path.abspath('.')) +# There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are +# entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support. +# We use these environment variables to thus get around that without locking +# ourselves in w.r.t. the multitude of operating systems this ought to build on. +# By default we assume a GCC-like compiler. +EXTRA_COMPILE_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_CFLAGS', + '-frtti -std=c++11')) +EXTRA_LINK_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_LDFLAGS', + '-lpthread')) + import protoc_lib_deps import grpc_version def protoc_ext_module(): plugin_sources = [ - 'grpc/protoc/main.cc', + 'grpc/tools/main.cc', 'grpc_root/src/compiler/python_generator.cc'] + [ os.path.join('third_party/protobuf/src', cc_file) for cc_file in protoc_lib_deps.CC_FILES] plugin_ext = extension.Extension( - name='grpc.protoc.protoc_compiler', - sources=['grpc/protoc/protoc_compiler.pyx'] + plugin_sources, + name='grpc.tools.protoc_compiler', + sources=['grpc/tools/protoc_compiler.pyx'] + plugin_sources, include_dirs=[ '.', 'grpc_root', @@ -60,7 +71,8 @@ def protoc_ext_module(): ], language='c++', define_macros=[('HAVE_PTHREAD', 1)], - extra_compile_args=['-lpthread', '-frtti', '-std=c++11'], + extra_compile_args=EXTRA_COMPILE_ARGS, + extra_link_args=EXTRA_LINK_ARGS, ) return plugin_ext @@ -71,7 +83,7 @@ def maybe_cythonize(exts): setuptools.setup( name='grpcio_tools', version=grpc_version.VERSION, - license='', + license='3-clause BSD', ext_modules=maybe_cythonize([ protoc_ext_module(), ]), diff --git a/tools/run_tests/artifact_targets.py b/tools/run_tests/artifact_targets.py index 477bd46888..bd1269ceb7 100644 --- a/tools/run_tests/artifact_targets.py +++ b/tools/run_tests/artifact_targets.py @@ -113,37 +113,7 @@ class PythonArtifact: # defines ourselves. # TODO(atash) get better platform-detection support in core so we don't # need to do this manually... - environ['CFLAGS'] = " ".join([ - '-DGPR_NO_AUTODETECT_PLATFORM', - '-DGPR_PLATFORM_STRING=\\"manylinux\\"', - '-DGPR_POSIX_CRASH_HANDLER=1', - '-DGPR_CPU_LINUX=1', - '-DGPR_GCC_ATOMIC=1', - '-DGPR_GCC_TLS=1', - '-DGPR_LINUX=1', - '-DGPR_LINUX_LOG=1', - #'-DGPR_LINUX_MULTIPOLL_WITH_EPOLL=1', - '-DGPR_POSIX_SOCKET=1', - '-DGPR_POSIX_WAKEUP_FD=1', - '-DGPR_POSIX_SOCKETADDR=1', - #'-DGPR_LINUX_EVENTFD=1', - '-DGPR_POSIX_NO_SPECIAL_WAKEUP_FD=1', - #'-DGPR_LINUX_SOCKETUTILS=1', - '-DGPR_POSIX_SOCKETUTILS=1', - '-DGPR_HAVE_UNIX_SOCKET=1', - '-DGPR_HAVE_IP_PKTINFO=1', - '-DGPR_HAVE_IPV6_RECVPKTINFO=1', - '-DGPR_LINUX_ENV=1', - '-DGPR_POSIX_FILE=1', - '-DGPR_POSIX_TMPFILE=1', - '-DGPR_POSIX_STRING=1', - '-DGPR_POSIX_SUBPROCESS=1', - '-DGPR_POSIX_SYNC=1', - '-DGPR_POSIX_TIME=1', - '-DGPR_GETPID_IN_UNISTD_H=1', - '-DGPR_HAVE_MSG_NOSIGNAL=1', - '-DGPR_ARCH_{arch}=1'.format(arch=('32' if self.arch == 'x86' else '64')), - ]) + environ['CFLAGS'] = '-DGPR_MANYLINUX1=1' return create_docker_jobspec(self.name, 'tools/dockerfile/grpc_artifact_python_manylinux_%s' % self.arch, 'tools/run_tests/build_artifact_python.sh', diff --git a/tools/run_tests/build_artifact_node.bat b/tools/run_tests/build_artifact_node.bat index 84c63c28a2..c5bd726db7 100644 --- a/tools/run_tests/build_artifact_node.bat +++ b/tools/run_tests/build_artifact_node.bat @@ -27,7 +27,7 @@ @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -set node_versions=0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 +set node_versions=0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm @@ -38,12 +38,12 @@ call npm update || goto :error mkdir artifacts for %%v in (%node_versions%) do ( - call node-pre-gyp configure build --target=%%v --target_arch=%1 + call .\node_modules\.bin\node-pre-gyp.cmd configure build --target=%%v --target_arch=%1 @rem Try again after removing openssl headers rmdir "%HOMEDRIVE%%HOMEPATH%\.node-gyp\%%v\include\node\openssl" /S /Q rmdir "%HOMEDRIVE%%HOMEPATH%\.node-gyp\iojs-%%v\include\node\openssl" /S /Q - call node-pre-gyp build package testpackage --target=%%v --target_arch=%1 || goto :error + call .\node_modules\.bin\node-pre-gyp.cmd build package testpackage --target=%%v --target_arch=%1 || goto :error xcopy /Y /I /S build\stage\* artifacts\ || goto :error ) diff --git a/tools/run_tests/build_artifact_node.sh b/tools/run_tests/build_artifact_node.sh index ef3476a038..9d06472aa4 100755 --- a/tools/run_tests/build_artifact_node.sh +++ b/tools/run_tests/build_artifact_node.sh @@ -42,7 +42,7 @@ mkdir -p artifacts npm update -node_versions=( 0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 ) +node_versions=( 0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 ) for version in ${node_versions[@]} do diff --git a/tools/run_tests/build_artifact_python.bat b/tools/run_tests/build_artifact_python.bat index 636ae0d393..fea0275426 100644 --- a/tools/run_tests/build_artifact_python.bat +++ b/tools/run_tests/build_artifact_python.bat @@ -41,7 +41,7 @@ copy /Y vsprojects\Release\grpc_dll.dll src\python\grpcio\grpc\_cython\_windows\ copy /Y vsprojects\x64\Release\grpc_dll.dll src\python\grpcio\grpc\_cython\_windows\grpc_c.64.python || goto :error -set PATH=C:\%1;C:\%1\scripts;%PATH% +set PATH=C:\%1;C:\%1\scripts;C:\msys64\mingw%2\bin;%PATH% pip install --upgrade six pip install --upgrade setuptools @@ -50,12 +50,26 @@ pip install -rrequirements.txt set GRPC_PYTHON_USE_CUSTOM_BDIST=0 set GRPC_PYTHON_BUILD_WITH_CYTHON=1 +@rem TODO(atash): maybe we could avoid the grpc_c.(32|64).python shim above if +@rem this used the right python build? python setup.py bdist_wheel @rem Build gRPC Python tools -set PATH=C:\msys64\mingw%2\bin;%PATH% -set CC=C:\msys64\mingw%2\bin\g++.exe -set CFLAGS=-fno-wrapv +@rem +@rem Because this is windows and *everything seems to hate Windows* we have to +@rem set all of these flags ourselves because Python won't help us (see the +@rem setup.py of the grpcio_tools project). +set GRPC_PYTHON_CFLAGS=-fno-wrapv -frtti -std=c++11 +@rem Further confusing things, MSYS2's mingw64 tries to dynamically link +@rem libgcc, libstdc++, and winpthreads. We have to override this or our +@rem extensions end up linking to MSYS2 DLLs, which the normal Python on +@rem Windows user won't have... and ON TOP OF THIS, there's MinGW's GCC default +@rem behavior of linking msvcrt.dll as the C runtime library, which we need to +@rem override so that Python's distutils doesn't link us against multiple C +@rem runtimes. +python -c "from distutils.cygwinccompiler import get_msvcr; print(get_msvcr()[0])" > temp.txt +set /p PYTHON_MSVCR=<temp.txt +set GRPC_PYTHON_LDFLAGS=-static-libgcc -static-libstdc++ -mcrtdll=%PYTHON_MSVCR% -static -lpthread python tools\distrib\python\make_grpcio_tools.py if %2 == 32 ( python tools\distrib\python\grpcio_tools\setup.py build_ext -c mingw32 diff --git a/tools/run_tests/build_artifact_python.sh b/tools/run_tests/build_artifact_python.sh index 35c3a48afa..4320f978e3 100755 --- a/tools/run_tests/build_artifact_python.sh +++ b/tools/run_tests/build_artifact_python.sh @@ -59,7 +59,11 @@ ${SETARCH_CMD} ${PYTHON} setup.py \ ${SETARCH_CMD} ${PYTHON} setup.py \ bdist_wheel -# Build gRPC tools package +# Build gRPC tools package source distribution +${SETARCH_CMD} ${PYTHON} tools/distrib/python/grpcio_tools/setup.py \ + sdist + +# Build gRPC tools package binary distribution ${PYTHON} tools/distrib/python/make_grpcio_tools.py CFLAGS="$CFLAGS -fno-wrapv" ${SETARCH_CMD} \ ${PYTHON} tools/distrib/python/grpcio_tools/setup.py bdist_wheel |