From 97e294aadc251c0fac5b417e55f207cedb10561e Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 23 Apr 2015 14:30:59 -0700 Subject: [PATCH 1/8] Removing some ugly hacks from C# server and improving the comments a bit --- .../Grpc.Core/Internal/CallSafeHandle.cs | 3 +- .../Grpc.Core/Internal/ServerSafeHandle.cs | 10 +- src/csharp/Grpc.Core/Server.cs | 176 +++++++++--------- .../Grpc.Examples.MathServer/MathServer.cs | 2 +- .../Grpc.IntegrationTesting.csproj | 4 +- 5 files changed, 107 insertions(+), 88 deletions(-) diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index 14add60c728..c97a3bc2b16 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -33,6 +33,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; using Grpc.Core; +using Grpc.Core.Utils; namespace Grpc.Core.Internal { @@ -180,7 +181,7 @@ namespace Grpc.Core.Internal private static void AssertCallOk(GRPCCallError callError) { - Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK"); + Preconditions.CheckState(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK"); } private static uint GetFlags(bool buffered) diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs index a59da098221..8080643d8c1 100644 --- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs @@ -35,6 +35,7 @@ using System; using System.Collections.Concurrent; using System.Diagnostics; using System.Runtime.InteropServices; +using Grpc.Core.Utils; namespace Grpc.Core.Internal { @@ -105,9 +106,9 @@ namespace Grpc.Core.Internal grpcsharp_server_shutdown_and_notify_CALLBACK(this, callback); } - public GRPCCallError RequestCall(CompletionQueueSafeHandle cq, CompletionCallbackDelegate callback) + public void RequestCall(CompletionQueueSafeHandle cq, CompletionCallbackDelegate callback) { - return grpcsharp_server_request_call(this, cq, callback); + AssertCallOk(grpcsharp_server_request_call(this, cq, callback)); } protected override bool ReleaseHandle() @@ -115,5 +116,10 @@ namespace Grpc.Core.Internal grpcsharp_server_destroy(handle); return true; } + + private static void AssertCallOk(GRPCCallError callError) + { + Preconditions.CheckState(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK"); + } } } diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs index f086fa8beb9..e686cdddef7 100644 --- a/src/csharp/Grpc.Core/Server.cs +++ b/src/csharp/Grpc.Core/Server.cs @@ -38,27 +38,29 @@ using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading.Tasks; using Grpc.Core.Internal; +using Grpc.Core.Utils; namespace Grpc.Core { /// - /// Server is implemented only to be able to do - /// in-process testing. + /// A gRPC server. /// public class Server { - // TODO: make sure the delegate doesn't get garbage collected while + // TODO(jtattermusch) : make sure the delegate doesn't get garbage collected while // native callbacks are in the completion queue. readonly ServerShutdownCallbackDelegate serverShutdownHandler; readonly CompletionCallbackDelegate newServerRpcHandler; - readonly BlockingCollection newRpcQueue = new BlockingCollection(); readonly ServerSafeHandle handle; + readonly object myLock = new object(); readonly Dictionary callHandlers = new Dictionary(); - readonly TaskCompletionSource shutdownTcs = new TaskCompletionSource(); + bool startRequested; + bool shutdownRequested; + public Server() { this.handle = ServerSafeHandle.NewServer(GetCompletionQueue(), IntPtr.Zero); @@ -66,71 +68,81 @@ namespace Grpc.Core this.serverShutdownHandler = HandleServerShutdown; } - // only call this before Start() + /// + /// Adds a service definition to the server. This is how you register + /// handlers for a service with the server. + /// Only call this before Start(). + /// public void AddServiceDefinition(ServerServiceDefinition serviceDefinition) { - foreach (var entry in serviceDefinition.CallHandlers) + lock (myLock) { - callHandlers.Add(entry.Key, entry.Value); + Preconditions.CheckState(!startRequested); + foreach (var entry in serviceDefinition.CallHandlers) + { + callHandlers.Add(entry.Key, entry.Value); + } } } - // only call before Start() + /// + /// Add a non-secure port on which server should listen. + /// Only call this before Start(). + /// public int AddListeningPort(string addr) { - return handle.AddListeningPort(addr); - } - - // only call before Start() - public int AddListeningPort(string addr, ServerCredentials credentials) - { - using (var nativeCredentials = credentials.ToNativeCredentials()) + lock (myLock) { - return handle.AddListeningPort(addr, nativeCredentials); + Preconditions.CheckState(!startRequested); + return handle.AddListeningPort(addr); } } - public void Start() - { - handle.Start(); - - // TODO: this basically means the server is single threaded.... - StartHandlingRpcs(); - } - /// - /// Requests and handles single RPC call. + /// Add a secure port on which server should listen. + /// Only call this before Start(). /// - internal void RunRpc() + public int AddListeningPort(string addr, ServerCredentials credentials) { - AllowOneRpc(); - - try + lock (myLock) { - var rpcInfo = newRpcQueue.Take(); - - // Console.WriteLine("Server received RPC " + rpcInfo.Method); - - IServerCallHandler callHandler; - if (!callHandlers.TryGetValue(rpcInfo.Method, out callHandler)) + Preconditions.CheckState(!startRequested); + using (var nativeCredentials = credentials.ToNativeCredentials()) { - callHandler = new NoSuchMethodCallHandler(); + return handle.AddListeningPort(addr, nativeCredentials); } - callHandler.StartCall(rpcInfo.Method, rpcInfo.Call, GetCompletionQueue()); } - catch (Exception e) + } + + /// + /// Starts the server. + /// + public void Start() + { + lock (myLock) { - Console.WriteLine("Exception while handling RPC: " + e); + Preconditions.CheckState(!startRequested); + startRequested = true; + + handle.Start(); + AllowOneRpc(); } } /// /// Requests server shutdown and when there are no more calls being serviced, - /// cleans up used resources. + /// cleans up used resources. The returned task finishes when shutdown procedure + /// is complete. /// - /// The async. public async Task ShutdownAsync() { + lock (myLock) + { + Preconditions.CheckState(startRequested); + Preconditions.CheckState(!shutdownRequested); + shutdownRequested = true; + } + handle.ShutdownAndNotify(serverShutdownHandler); await shutdownTcs.Task; handle.Dispose(); @@ -152,19 +164,43 @@ namespace Grpc.Core handle.Dispose(); } - private async Task StartHandlingRpcs() + /// + /// Allows one new RPC call to be received by server. + /// + private void AllowOneRpc() { - while (true) + lock (myLock) { - await Task.Factory.StartNew(RunRpc); + if (!shutdownRequested) + { + handle.RequestCall(GetCompletionQueue(), newServerRpcHandler); + } } } - private void AllowOneRpc() + /// + /// Selects corresponding handler for given call and handles the call. + /// + private void InvokeCallHandler(CallSafeHandle call, string method) { - AssertCallOk(handle.RequestCall(GetCompletionQueue(), newServerRpcHandler)); + try + { + IServerCallHandler callHandler; + if (!callHandlers.TryGetValue(method, out callHandler)) + { + callHandler = new NoSuchMethodCallHandler(); + } + callHandler.StartCall(method, call, GetCompletionQueue()); + } + catch (Exception e) + { + Console.WriteLine("Exception while handling RPC: " + e); + } } + /// + /// Handles the native callback. + /// private void HandleNewServerRpc(GRPCOpError error, IntPtr batchContextPtr) { try @@ -176,13 +212,16 @@ namespace Grpc.Core // TODO: handle error } - var rpcInfo = new NewRpcInfo(ctx.GetServerRpcNewCall(), ctx.GetServerRpcNewMethod()); + CallSafeHandle call = ctx.GetServerRpcNewCall(); + string method = ctx.GetServerRpcNewMethod(); // after server shutdown, the callback returns with null call - if (!rpcInfo.Call.IsInvalid) + if (!call.IsInvalid) { - newRpcQueue.Add(rpcInfo); + Task.Run(() => InvokeCallHandler(call, method)); } + + AllowOneRpc(); } catch (Exception e) { @@ -190,6 +229,10 @@ namespace Grpc.Core } } + /// + /// Handles native callback. + /// + /// private void HandleServerShutdown(IntPtr eventPtr) { try @@ -202,42 +245,9 @@ namespace Grpc.Core } } - private static void AssertCallOk(GRPCCallError callError) - { - Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK"); - } - private static CompletionQueueSafeHandle GetCompletionQueue() { return GrpcEnvironment.ThreadPool.CompletionQueue; } - - private struct NewRpcInfo - { - private CallSafeHandle call; - private string method; - - public NewRpcInfo(CallSafeHandle call, string method) - { - this.call = call; - this.method = method; - } - - public CallSafeHandle Call - { - get - { - return this.call; - } - } - - public string Method - { - get - { - return this.method; - } - } - } } } diff --git a/src/csharp/Grpc.Examples.MathServer/MathServer.cs b/src/csharp/Grpc.Examples.MathServer/MathServer.cs index 884a84d0a6c..c26763e622b 100644 --- a/src/csharp/Grpc.Examples.MathServer/MathServer.cs +++ b/src/csharp/Grpc.Examples.MathServer/MathServer.cs @@ -40,7 +40,7 @@ namespace math { public static void Main(string[] args) { - String host = "0.0.0.0"; + string host = "0.0.0.0"; GrpcEnvironment.Initialize(); diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 584bf1068de..6ae8041fb7c 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -80,5 +80,7 @@ PreserveNewest - + + + \ No newline at end of file From 117cc1207dea83894c85401031577eb1548f3a18 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Fri, 24 Apr 2015 07:24:50 -0700 Subject: [PATCH 2/8] Fix failing interop servers --- src/ruby/lib/grpc/generic/rpc_server.rb | 27 +++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 88c24aa92bb..3375fcf20ac 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -54,6 +54,18 @@ module GRPC 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 @@ -172,17 +184,6 @@ module GRPC # Signal check period is 0.25s SIGNAL_CHECK_PERIOD = 0.25 - # 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 self.trap_signals - %w(INT TERM).each { |sig| trap(sig) { $grpc_signals << sig } } - end - # setup_cq is used by #initialize to constuct a Core::CompletionQueue from # its arguments. def self.setup_cq(alt_cq) @@ -299,12 +300,12 @@ module GRPC # 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 - self.class.trap_signals + GRPC.trap_signals t = Thread.new { run } wait_till_running loop do sleep SIGNAL_CHECK_PERIOD - break unless handle_signals + break unless GRPC.handle_signals end stop t.join From 119decc0f4c7097764fc6610088c69c636e853e0 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Fri, 24 Apr 2015 07:25:16 -0700 Subject: [PATCH 3/8] Fix logging version mismatchj --- src/ruby/grpc.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec index c6335791025..19b3e21cb6d 100755 --- a/src/ruby/grpc.gemspec +++ b/src/ruby/grpc.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1' s.add_dependency 'googleauth', '~> 0.4' # reqd for interop tests - s.add_dependency 'logging', '~> 1.8' + s.add_dependency 'logging', '~> 2.0' s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests s.add_development_dependency 'simplecov', '~> 0.9' From 0a6557809a1e855dbbcbfde816640b349ae9652d Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Fri, 24 Apr 2015 07:36:28 -0700 Subject: [PATCH 4/8] Simplify debugging, avoid inspecting C-backed objects. --- src/ruby/lib/grpc/generic/active_call.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb index 43ba5499059..947c39cd226 100644 --- a/src/ruby/lib/grpc/generic/active_call.rb +++ b/src/ruby/lib/grpc/generic/active_call.rb @@ -188,7 +188,7 @@ module GRPC # @param marshalled [false, true] indicates if the object is already # marshalled. def remote_send(req, marshalled = false) - logger.debug("sending #{req.inspect}, marshalled? #{marshalled}") + logger.debug("sending #{req}, marshalled? #{marshalled}") if marshalled payload = req else From 9cb56f8707f39d5c81e533de9118137129b20eda Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Fri, 24 Apr 2015 08:13:01 -0700 Subject: [PATCH 5/8] Move Notifier into its own file --- src/ruby/lib/grpc.rb | 1 + src/ruby/lib/grpc/generic/bidi_call.rb | 3 +- src/ruby/lib/grpc/notifier.rb | 60 +++++++++++++++++++++++ src/ruby/spec/generic/client_stub_spec.rb | 31 +----------- 4 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 src/ruby/lib/grpc/notifier.rb diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb index b0f68035cd6..80b5743e914 100644 --- a/src/ruby/lib/grpc.rb +++ b/src/ruby/lib/grpc.rb @@ -30,6 +30,7 @@ require 'grpc/errors' require 'grpc/grpc' require 'grpc/logconfig' +require 'grpc/notifier' require 'grpc/version' require 'grpc/core/time_consts' require 'grpc/generic/active_call' diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb index b813ab5b542..4ca3004d6f0 100644 --- a/src/ruby/lib/grpc/generic/bidi_call.rb +++ b/src/ruby/lib/grpc/generic/bidi_call.rb @@ -123,8 +123,7 @@ module GRPC break if req.equal?(END_OF_READS) yield req end - @loop_th.join - @enq_th.join + @enq_th.join if @enq_th.alive? end # during bidi-streaming, read the requests to send from a separate thread diff --git a/src/ruby/lib/grpc/notifier.rb b/src/ruby/lib/grpc/notifier.rb new file mode 100644 index 00000000000..caa18bbed6d --- /dev/null +++ b/src/ruby/lib/grpc/notifier.rb @@ -0,0 +1,60 @@ +# 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. + +# GRPC contains the General RPC module. +module GRPC + # Notifier is useful high-level synchronization primitive. + class Notifier + attr_reader :payload, :notified + alias_method :notified?, :notified + + def initialize + @mutex = Mutex.new + @cvar = ConditionVariable.new + @notified = false + @payload = nil + end + + def wait + @mutex.synchronize do + @cvar.wait(@mutex) until notified? + end + end + + def notify(payload) + @mutex.synchronize do + return Error.new('already notified') if notified? + @payload = payload + @notified = true + @cvar.signal + return nil + end + end + end +end diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb index 88c6b44c229..98d68ccfbb8 100644 --- a/src/ruby/spec/generic/client_stub_spec.rb +++ b/src/ruby/spec/generic/client_stub_spec.rb @@ -29,37 +29,8 @@ require 'grpc' -# Notifier is useful high-level synchronization primitive. -class Notifier - attr_reader :payload, :notified - alias_method :notified?, :notified - - def initialize - @mutex = Mutex.new - @cvar = ConditionVariable.new - @notified = false - @payload = nil - end - - def wait - @mutex.synchronize do - @cvar.wait(@mutex) until notified? - end - end - - def notify(payload) - @mutex.synchronize do - return Error.new('already notified') if notified? - @payload = payload - @notified = true - @cvar.signal - return nil - end - end -end - def wakey_thread(&blk) - n = Notifier.new + n = GRPC::Notifier.new t = Thread.new do blk.call(n) end From 932b13be4c14576ca3c5d3bed49333b49be7372c Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Fri, 24 Apr 2015 08:52:46 -0700 Subject: [PATCH 6/8] Corrects bad return values in C error-handling block --- src/ruby/ext/grpc/rb_call.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c index 6da7d3c8305..f4ae6fab846 100644 --- a/src/ruby/ext/grpc/rb_call.c +++ b/src/ruby/ext/grpc/rb_call.c @@ -607,19 +607,19 @@ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE cqueue, VALUE tag, rb_raise(grpc_rb_eCallError, "grpc_call_start_batch failed with %s (code=%d)", grpc_call_error_detail_of(err), err); - return; + return Qnil; } ev = grpc_rb_completion_queue_pluck_event(cqueue, tag, timeout); if (ev == NULL) { grpc_run_batch_stack_cleanup(&st); rb_raise(grpc_rb_eOutOfTime, "grpc_call_start_batch timed out"); - return; + return Qnil; } if (ev->data.op_complete != GRPC_OP_OK) { grpc_run_batch_stack_cleanup(&st); rb_raise(grpc_rb_eCallError, "start_batch completion failed, (code=%d)", ev->data.op_complete); - return; + return Qnil; } /* Build and return the BatchResult struct result */ From c4b6ffb1b6aa9fb3c5fbf15a5e7e2862cfc4624c Mon Sep 17 00:00:00 2001 From: Yang Gao Date: Thu, 23 Apr 2015 16:35:24 -0700 Subject: [PATCH 7/8] Add a GrpcLibrary class to wrap grpc_init and grpc_shutdown and convert all the tests to init/shutdown free. --- examples/pubsub/main.cc | 3 -- examples/pubsub/publisher_test.cc | 2 - examples/pubsub/subscriber_test.cc | 2 - include/grpc++/completion_queue.h | 5 ++- include/grpc++/credentials.h | 5 ++- include/grpc++/impl/grpc_library.h | 50 ++++++++++++++++++++++++ include/grpc++/server.h | 4 +- src/cpp/client/channel.h | 4 +- test/cpp/client/credentials_test.cc | 2 - test/cpp/end2end/async_end2end_test.cc | 5 +-- test/cpp/end2end/end2end_test.cc | 5 +-- test/cpp/end2end/generic_end2end_test.cc | 5 +-- test/cpp/interop/client.cc | 4 -- test/cpp/interop/server.cc | 2 - test/cpp/qps/qps_driver.cc | 2 - test/cpp/qps/smoke_test.cc | 3 -- test/cpp/qps/worker.cc | 4 +- test/cpp/util/cli_call_test.cc | 5 +-- test/cpp/util/grpc_cli.cc | 4 -- 19 files changed, 67 insertions(+), 49 deletions(-) create mode 100644 include/grpc++/impl/grpc_library.h diff --git a/examples/pubsub/main.cc b/examples/pubsub/main.cc index 8f8eefa9efb..3a403481fcd 100644 --- a/examples/pubsub/main.cc +++ b/examples/pubsub/main.cc @@ -65,7 +65,6 @@ const char kMessageData[] = "Test Data"; } // namespace int main(int argc, char** argv) { - grpc_init(); grpc::testing::InitTest(&argc, &argv, true); gpr_log(GPR_INFO, "Start PUBSUB client"); @@ -146,7 +145,5 @@ int main(int argc, char** argv) { subscriber.Shutdown(); publisher.Shutdown(); - channel.reset(); - grpc_shutdown(); return 0; } diff --git a/examples/pubsub/publisher_test.cc b/examples/pubsub/publisher_test.cc index ac4921283f4..6b9dcacc499 100644 --- a/examples/pubsub/publisher_test.cc +++ b/examples/pubsub/publisher_test.cc @@ -148,10 +148,8 @@ TEST_F(PublisherTest, TestPublisher) { int main(int argc, char** argv) { grpc_test_init(argc, argv); - grpc_init(); ::testing::InitGoogleTest(&argc, argv); gpr_log(GPR_INFO, "Start test ..."); int result = RUN_ALL_TESTS(); - grpc_shutdown(); return result; } diff --git a/examples/pubsub/subscriber_test.cc b/examples/pubsub/subscriber_test.cc index 9ab60ed6a76..b0e7fc034b8 100644 --- a/examples/pubsub/subscriber_test.cc +++ b/examples/pubsub/subscriber_test.cc @@ -147,10 +147,8 @@ TEST_F(SubscriberTest, TestSubscriber) { int main(int argc, char** argv) { grpc_test_init(argc, argv); - grpc_init(); ::testing::InitGoogleTest(&argc, argv); gpr_log(GPR_INFO, "Start test ..."); int result = RUN_ALL_TESTS(); - grpc_shutdown(); return result; } diff --git a/include/grpc++/completion_queue.h b/include/grpc++/completion_queue.h index e6a8c6fe552..0a2a7687b75 100644 --- a/include/grpc++/completion_queue.h +++ b/include/grpc++/completion_queue.h @@ -36,6 +36,7 @@ #include #include +#include #include struct grpc_completion_queue; @@ -71,11 +72,11 @@ class CompletionQueueTag { }; // grpc_completion_queue wrapper class -class CompletionQueue { +class CompletionQueue : public GrpcLibrary { public: CompletionQueue(); explicit CompletionQueue(grpc_completion_queue* take); - ~CompletionQueue(); + ~CompletionQueue() GRPC_OVERRIDE; // Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT enum NextStatus { SHUTDOWN, GOT_EVENT, TIMEOUT }; diff --git a/include/grpc++/credentials.h b/include/grpc++/credentials.h index 2ac3eec95cd..cbf94457508 100644 --- a/include/grpc++/credentials.h +++ b/include/grpc++/credentials.h @@ -38,15 +38,16 @@ #include #include +#include namespace grpc { class ChannelArguments; class ChannelInterface; class SecureCredentials; -class Credentials { +class Credentials : public GrpcLibrary { public: - virtual ~Credentials(); + ~Credentials() GRPC_OVERRIDE; protected: friend std::unique_ptr CompositeCredentials( diff --git a/include/grpc++/impl/grpc_library.h b/include/grpc++/impl/grpc_library.h new file mode 100644 index 00000000000..f9fa677901b --- /dev/null +++ b/include/grpc++/impl/grpc_library.h @@ -0,0 +1,50 @@ +/* + * + * 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. + * + */ + +#ifndef GRPCXX_IMPL_GRPC_LIBRARY_H +#define GRPCXX_IMPL_GRPC_LIBRARY_H + +#include + +namespace grpc { + +class GrpcLibrary { + public: + GrpcLibrary() { grpc_init(); } + virtual ~GrpcLibrary() { grpc_shutdown(); } +}; + +} // namespace grpc + + +#endif // GRPCXX_IMPL_GRPC_LIBRARY_H diff --git a/include/grpc++/server.h b/include/grpc++/server.h index eb506115735..0ae27e9e9f8 100644 --- a/include/grpc++/server.h +++ b/include/grpc++/server.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,8 @@ class ServerCredentials; class ThreadPoolInterface; // Currently it only supports handling rpcs in a single thread. -class Server GRPC_FINAL : private CallHook, +class Server GRPC_FINAL : public GrpcLibrary, + private CallHook, private AsynchronousService::DispatchImpl { public: ~Server(); diff --git a/src/cpp/client/channel.h b/src/cpp/client/channel.h index aaf4dbe10dc..cd239247c82 100644 --- a/src/cpp/client/channel.h +++ b/src/cpp/client/channel.h @@ -38,6 +38,7 @@ #include #include +#include struct grpc_channel; @@ -49,7 +50,8 @@ class CompletionQueue; class Credentials; class StreamContextInterface; -class Channel GRPC_FINAL : public ChannelInterface { +class Channel GRPC_FINAL : public GrpcLibrary, + public ChannelInterface { public: Channel(const grpc::string& target, grpc_channel* c_channel); ~Channel() GRPC_OVERRIDE; diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc index 24251f297be..883f1dca7b9 100644 --- a/test/cpp/client/credentials_test.cc +++ b/test/cpp/client/credentials_test.cc @@ -56,8 +56,6 @@ TEST_F(CredentialsTest, InvalidServiceAccountCreds) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - grpc_init(); int ret = RUN_ALL_TESTS(); - grpc_shutdown(); return ret; } diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index dd294d95163..e3cbfd6f8df 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -595,9 +595,6 @@ TEST_F(AsyncEnd2endTest, MetadataRpc) { int main(int argc, char** argv) { grpc_test_init(argc, argv); - grpc_init(); ::testing::InitGoogleTest(&argc, argv); - int result = RUN_ALL_TESTS(); - grpc_shutdown(); - return result; + return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 2d3b405d1c0..f63854ccf31 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -562,9 +562,6 @@ TEST_F(End2endTest, ClientCancelsBidi) { int main(int argc, char** argv) { grpc_test_init(argc, argv); - grpc_init(); ::testing::InitGoogleTest(&argc, argv); - int result = RUN_ALL_TESTS(); - grpc_shutdown(); - return result; + return RUN_ALL_TESTS(); } diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc index 584d4bc7ba0..e70a1cb68b5 100644 --- a/test/cpp/end2end/generic_end2end_test.cc +++ b/test/cpp/end2end/generic_end2end_test.cc @@ -280,9 +280,6 @@ TEST_F(GenericEnd2endTest, SimpleBidiStreaming) { int main(int argc, char** argv) { grpc_test_init(argc, argv); - grpc_init(); ::testing::InitGoogleTest(&argc, argv); - int result = RUN_ALL_TESTS(); - grpc_shutdown(); - return result; + return RUN_ALL_TESTS(); } diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index 42d16f2f85e..072968f7cdc 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -76,8 +76,6 @@ using grpc::testing::CreateChannelForTestCase; using grpc::testing::GetServiceAccountJsonKey; int main(int argc, char** argv) { - grpc_init(); - grpc::testing::InitTest(&argc, &argv, true); int ret = 0; @@ -129,8 +127,6 @@ int main(int argc, char** argv) { FLAGS_test_case.c_str()); ret = 1; } - client.Reset(nullptr); - grpc_shutdown(); return ret; } diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc index 7888102837a..22b8910a249 100644 --- a/test/cpp/interop/server.cc +++ b/test/cpp/interop/server.cc @@ -218,13 +218,11 @@ void RunServer() { static void sigint_handler(int x) { got_sigint = true; } int main(int argc, char** argv) { - grpc_init(); grpc::testing::InitTest(&argc, &argv, true); signal(SIGINT, sigint_handler); GPR_ASSERT(FLAGS_port != 0); RunServer(); - grpc_shutdown(); return 0; } diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc index 0669ccf808b..93b1247d739 100644 --- a/test/cpp/qps/qps_driver.cc +++ b/test/cpp/qps/qps_driver.cc @@ -69,7 +69,6 @@ using grpc::testing::RpcType; using grpc::testing::ResourceUsage; int main(int argc, char** argv) { - grpc_init(); grpc::testing::InitTest(&argc, &argv, true); RpcType rpc_type; @@ -104,6 +103,5 @@ int main(int argc, char** argv) { ReportLatency(result); ReportTimes(result); - grpc_shutdown(); return 0; } diff --git a/test/cpp/qps/smoke_test.cc b/test/cpp/qps/smoke_test.cc index 9531913b00e..e3907308325 100644 --- a/test/cpp/qps/smoke_test.cc +++ b/test/cpp/qps/smoke_test.cc @@ -136,14 +136,11 @@ static void RunQPS() { } // namespace grpc int main(int argc, char** argv) { - grpc_init(); - using namespace grpc::testing; RunSynchronousStreamingPingPong(); RunSynchronousUnaryPingPong(); RunAsyncUnaryPingPong(); RunQPS(); - grpc_shutdown(); return 0; } diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index 896a85cc593..281c617382a 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -64,13 +64,11 @@ static void RunServer() { } // namespace grpc int main(int argc, char** argv) { - grpc_init(); grpc::testing::InitTest(&argc, &argv, true); signal(SIGINT, sigint_handler); grpc::testing::RunServer(); - - grpc_shutdown(); + return 0; } diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc index 32ef392cc4c..457a5e77de8 100644 --- a/test/cpp/util/cli_call_test.cc +++ b/test/cpp/util/cli_call_test.cc @@ -123,9 +123,6 @@ TEST_F(CliCallTest, SimpleRpc) { int main(int argc, char** argv) { grpc_test_init(argc, argv); - grpc_init(); ::testing::InitGoogleTest(&argc, argv); - int result = RUN_ALL_TESTS(); - grpc_shutdown(); - return result; + return RUN_ALL_TESTS(); } diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc index ee9f2752737..d71a7a0b778 100644 --- a/test/cpp/util/grpc_cli.cc +++ b/test/cpp/util/grpc_cli.cc @@ -79,8 +79,6 @@ DEFINE_string(output_binary_file, "output.bin", "Path to output file to write serialized response."); int main(int argc, char** argv) { - grpc_init(); - grpc::testing::InitTest(&argc, &argv, true); if (argc < 4 || grpc::string(argv[1]) != "call") { @@ -127,7 +125,5 @@ int main(int argc, char** argv) { output_file << response; } - channel.reset(); - grpc_shutdown(); return 0; } From 96de48449ccc6009bc745ab5ff35837a4720fdd1 Mon Sep 17 00:00:00 2001 From: Yang Gao Date: Fri, 24 Apr 2015 13:13:12 -0700 Subject: [PATCH 8/8] Add the new header to build.json and regenerate projects --- BUILD | 2 ++ Makefile | 2 ++ build.json | 1 + vsprojects/grpc++/grpc++.vcxproj | 1 + vsprojects/grpc++/grpc++.vcxproj.filters | 3 +++ 5 files changed, 9 insertions(+) diff --git a/BUILD b/BUILD index 2a93161db2b..79070f1c1ef 100644 --- a/BUILD +++ b/BUILD @@ -621,6 +621,7 @@ cc_library( "include/grpc++/generic_stub.h", "include/grpc++/impl/call.h", "include/grpc++/impl/client_unary_call.h", + "include/grpc++/impl/grpc_library.h", "include/grpc++/impl/internal_stub.h", "include/grpc++/impl/rpc_method.h", "include/grpc++/impl/rpc_service_method.h", @@ -699,6 +700,7 @@ cc_library( "include/grpc++/generic_stub.h", "include/grpc++/impl/call.h", "include/grpc++/impl/client_unary_call.h", + "include/grpc++/impl/grpc_library.h", "include/grpc++/impl/internal_stub.h", "include/grpc++/impl/rpc_method.h", "include/grpc++/impl/rpc_service_method.h", diff --git a/Makefile b/Makefile index 3e7930b9c36..8cd71600ade 100644 --- a/Makefile +++ b/Makefile @@ -3854,6 +3854,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc++/generic_stub.h \ include/grpc++/impl/call.h \ include/grpc++/impl/client_unary_call.h \ + include/grpc++/impl/grpc_library.h \ include/grpc++/impl/internal_stub.h \ include/grpc++/impl/rpc_method.h \ include/grpc++/impl/rpc_service_method.h \ @@ -4117,6 +4118,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc++/generic_stub.h \ include/grpc++/impl/call.h \ include/grpc++/impl/client_unary_call.h \ + include/grpc++/impl/grpc_library.h \ include/grpc++/impl/internal_stub.h \ include/grpc++/impl/rpc_method.h \ include/grpc++/impl/rpc_service_method.h \ diff --git a/build.json b/build.json index 8838d3a6301..ec48314d266 100644 --- a/build.json +++ b/build.json @@ -28,6 +28,7 @@ "include/grpc++/generic_stub.h", "include/grpc++/impl/call.h", "include/grpc++/impl/client_unary_call.h", + "include/grpc++/impl/grpc_library.h", "include/grpc++/impl/internal_stub.h", "include/grpc++/impl/rpc_method.h", "include/grpc++/impl/rpc_service_method.h", diff --git a/vsprojects/grpc++/grpc++.vcxproj b/vsprojects/grpc++/grpc++.vcxproj index 38eca1a14e5..07c018f1110 100644 --- a/vsprojects/grpc++/grpc++.vcxproj +++ b/vsprojects/grpc++/grpc++.vcxproj @@ -96,6 +96,7 @@ + diff --git a/vsprojects/grpc++/grpc++.vcxproj.filters b/vsprojects/grpc++/grpc++.vcxproj.filters index 6466a0fa26e..46b33bb8a66 100644 --- a/vsprojects/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/grpc++/grpc++.vcxproj.filters @@ -120,6 +120,9 @@ include\grpc++\impl + + include\grpc++\impl + include\grpc++\impl