From 8a507811ff14502131474eb3bf799c14419579a6 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 8 May 2017 16:30:12 +0200 Subject: C# workaround for unavailable on idle channels --- src/csharp/Grpc.Core/Channel.cs | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs index 4f29c35b32..51ae11fbde 100644 --- a/src/csharp/Grpc.Core/Channel.cs +++ b/src/csharp/Grpc.Core/Channel.cs @@ -59,6 +59,8 @@ namespace Grpc.Core readonly ChannelSafeHandle handle; readonly Dictionary options; + readonly Task connectivityWatcherTask; + bool shutdownRequested; /// @@ -99,6 +101,9 @@ namespace Grpc.Core this.handle = ChannelSafeHandle.CreateInsecure(target, nativeChannelArgs); } } + // TODO(jtattermusch): Workaround for https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/822. + // Remove once retries are supported in C core + this.connectivityWatcherTask = RunConnectivityWatcherAsync(); GrpcEnvironment.RegisterChannel(this); } @@ -244,7 +249,7 @@ namespace Grpc.Core handle.Dispose(); - await GrpcEnvironment.ReleaseAsync().ConfigureAwait(false); + await Task.WhenAll(GrpcEnvironment.ReleaseAsync(), connectivityWatcherTask).ConfigureAwait(false); } internal ChannelSafeHandle Handle @@ -299,6 +304,40 @@ namespace Grpc.Core } } + /// + /// Constantly Watches channel connectivity status to work around https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/822 + /// + private async Task RunConnectivityWatcherAsync() + { + try + { + var lastState = State; + while (lastState != ChannelState.Shutdown) + { + lock (myLock) + { + if (shutdownRequested) + { + break; + } + } + + try + { + await WaitForStateChangedAsync(lastState, DateTime.UtcNow.AddSeconds(1)).ConfigureAwait(false); + } + catch (TaskCanceledException) + { + // ignore timeout + } + lastState = State; + } + } + catch (ObjectDisposedException) { + // during shutdown, channel is going to be disposed. + } + } + private static void EnsureUserAgentChannelOption(Dictionary options) { var key = ChannelOptions.PrimaryUserAgentString; -- cgit v1.2.3 From b2c0b7bc7411c0914e2f65d56096ecde1a207b53 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 27 Apr 2017 00:26:25 -0700 Subject: constant state watch without timeouts --- src/ruby/end2end/channel_closing_driver.rb | 5 + src/ruby/end2end/channel_state_driver.rb | 3 + src/ruby/end2end/grpc_class_init_client.rb | 65 ++- src/ruby/end2end/grpc_class_init_driver.rb | 51 ++- .../end2end/sig_int_during_channel_watch_client.rb | 2 + .../end2end/sig_int_during_channel_watch_driver.rb | 5 + src/ruby/ext/grpc/rb_call.c | 2 +- src/ruby/ext/grpc/rb_channel.c | 494 ++++++++++++++------- src/ruby/ext/grpc/rb_completion_queue.c | 14 +- src/ruby/ext/grpc/rb_completion_queue.h | 2 +- src/ruby/ext/grpc/rb_event_thread.c | 12 +- src/ruby/ext/grpc/rb_server.c | 2 +- src/ruby/spec/channel_connection_spec.rb | 35 +- 13 files changed, 472 insertions(+), 220 deletions(-) diff --git a/src/ruby/end2end/channel_closing_driver.rb b/src/ruby/end2end/channel_closing_driver.rb index d3e5373b0b..bed8c43405 100755 --- a/src/ruby/end2end/channel_closing_driver.rb +++ b/src/ruby/end2end/channel_closing_driver.rb @@ -61,6 +61,11 @@ def main 'channel is closed while connectivity is watched' end + client_exit_code = $CHILD_STATUS + if client_exit_code != 0 + fail "channel closing client failed, exit code #{client_exit_code}" + end + server_runner.stop end diff --git a/src/ruby/end2end/channel_state_driver.rb b/src/ruby/end2end/channel_state_driver.rb index 80fb62899e..9910076dba 100755 --- a/src/ruby/end2end/channel_state_driver.rb +++ b/src/ruby/end2end/channel_state_driver.rb @@ -58,6 +58,9 @@ def main 'It likely hangs when ended abruptly' end + # The interrupt in the child process should cause it to + # exit a non-zero status, so don't check it here. + # This test mainly tries to catch deadlock. server_runner.stop end diff --git a/src/ruby/end2end/grpc_class_init_client.rb b/src/ruby/end2end/grpc_class_init_client.rb index ee79292119..8e46907368 100755 --- a/src/ruby/end2end/grpc_class_init_client.rb +++ b/src/ruby/end2end/grpc_class_init_client.rb @@ -34,44 +34,81 @@ require_relative './end2end_common' -def main - grpc_class = '' - OptionParser.new do |opts| - opts.on('--grpc_class=P', String) do |p| - grpc_class = p +def construct_many(test_proc) + thds = [] + 4.times do + thds << Thread.new do + 20.times do + test_proc.call + end end - end.parse! + end + 20.times do + test_proc.call + end + thds.each(&:join) +end + +def run_gc_stress_test(test_proc) + GC.disable + construct_many(test_proc) - test_proc = nil + GC.enable + construct_many(test_proc) + GC.start(full_mark: true, immediate_sweep: true) + construct_many(test_proc) +end + +def get_test_proc(grpc_class) case grpc_class when 'channel' - test_proc = proc do + return proc do GRPC::Core::Channel.new('dummy_host', nil, :this_channel_is_insecure) end when 'server' - test_proc = proc do + return proc do GRPC::Core::Server.new({}) end when 'channel_credentials' - test_proc = proc do + return proc do GRPC::Core::ChannelCredentials.new end when 'call_credentials' - test_proc = proc do + return proc do GRPC::Core::CallCredentials.new(proc { |noop| noop }) end when 'compression_options' - test_proc = proc do + return proc do GRPC::Core::CompressionOptions.new end else fail "bad --grpc_class=#{grpc_class} param" end +end + +def main + grpc_class = '' + gc_stress = false + OptionParser.new do |opts| + opts.on('--grpc_class=P', String) do |p| + grpc_class = p + end + opts.on('--gc_stress=P') do |p| + gc_stress = p + end + end.parse! + + test_proc = get_test_proc(grpc_class) + + if gc_stress == 'true' + run_gc_stress_test(test_proc) + return + end - th = Thread.new { test_proc.call } + thd = Thread.new { test_proc.call } test_proc.call - th.join + thd.join end main diff --git a/src/ruby/end2end/grpc_class_init_driver.rb b/src/ruby/end2end/grpc_class_init_driver.rb index 764d029f14..0e330a493f 100755 --- a/src/ruby/end2end/grpc_class_init_driver.rb +++ b/src/ruby/end2end/grpc_class_init_driver.rb @@ -38,29 +38,38 @@ def main call_credentials compression_options ) - native_grpc_classes.each do |grpc_class| - STDERR.puts 'start client' - this_dir = File.expand_path(File.dirname(__FILE__)) - client_path = File.join(this_dir, 'grpc_class_init_client.rb') - client_pid = Process.spawn(RbConfig.ruby, - client_path, - "--grpc_class=#{grpc_class}") - begin - Timeout.timeout(10) do - Process.wait(client_pid) + # there is room for false positives in this test, + # do 10 runs for each config to reduce these. + [true, false].each do |gc_stress| + 10.times do + native_grpc_classes.each do |grpc_class| + STDERR.puts 'start client' + this_dir = File.expand_path(File.dirname(__FILE__)) + client_path = File.join(this_dir, 'grpc_class_init_client.rb') + client_pid = Process.spawn(RbConfig.ruby, + client_path, + "--grpc_class=#{grpc_class}", + "--gc_stress=#{gc_stress}") + begin + Timeout.timeout(10) do + Process.wait(client_pid) + end + rescue Timeout::Error + STDERR.puts "timeout waiting for client pid #{client_pid}" + Process.kill('SIGKILL', client_pid) + Process.wait(client_pid) + STDERR.puts 'killed client child' + raise 'Timed out waiting for client process. ' \ + 'It likely hangs when the first constructed gRPC object has ' \ + "type: #{grpc_class}" + end + + client_exit_code = $CHILD_STATUS + if client_exit_code != 0 + fail "client failed, exit code #{client_exit_code}" + end end - rescue Timeout::Error - STDERR.puts "timeout waiting for client pid #{client_pid}" - Process.kill('SIGKILL', client_pid) - Process.wait(client_pid) - STDERR.puts 'killed client child' - raise 'Timed out waiting for client process. ' \ - 'It likely hangs when the first constructed gRPC object has ' \ - "type: #{grpc_class}" end - - client_exit_code = $CHILD_STATUS - fail "client failed, exit code #{client_exit_code}" if client_exit_code != 0 end end diff --git a/src/ruby/end2end/sig_int_during_channel_watch_client.rb b/src/ruby/end2end/sig_int_during_channel_watch_client.rb index 389fc5ba33..0c6a374925 100755 --- a/src/ruby/end2end/sig_int_during_channel_watch_client.rb +++ b/src/ruby/end2end/sig_int_during_channel_watch_client.rb @@ -46,6 +46,8 @@ def main end end.parse! + trap('SIGINT') { exit 0 } + thd = Thread.new do child_thread_channel = GRPC::Core::Channel.new("localhost:#{server_port}", {}, diff --git a/src/ruby/end2end/sig_int_during_channel_watch_driver.rb b/src/ruby/end2end/sig_int_during_channel_watch_driver.rb index 670cda0919..79a8c133fa 100755 --- a/src/ruby/end2end/sig_int_during_channel_watch_driver.rb +++ b/src/ruby/end2end/sig_int_during_channel_watch_driver.rb @@ -63,6 +63,11 @@ def main 'SIGINT is sent while there is an active connectivity_state call' end + client_exit_code = $CHILD_STATUS + if client_exit_code != 0 + fail "sig_int_during_channel_watch_client failed: #{client_exit_code}" + end + server_runner.stop end diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c index 344cb941ff..6cb71870f5 100644 --- a/src/ruby/ext/grpc/rb_call.c +++ b/src/ruby/ext/grpc/rb_call.c @@ -103,7 +103,7 @@ static void destroy_call(grpc_rb_call *call) { if (call->wrapped != NULL) { grpc_call_destroy(call->wrapped); call->wrapped = NULL; - grpc_rb_completion_queue_destroy(call->queue); + grpc_rb_completion_queue_safe_destroy(call->queue); call->queue = NULL; } } diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index fb610f548e..973a45adf5 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -52,75 +52,131 @@ /* id_channel is the name of the hidden ivar that preserves a reference to the * channel on a call, so that calls are not GCed before their channel. */ -static ID id_channel; +ID id_channel; /* id_target is the name of the hidden ivar that preserves a reference to the * target string used to create the call, preserved so that it does not get * GCed before the channel */ -static ID id_target; +ID id_target; /* id_insecure_channel is used to indicate that a channel is insecure */ -static VALUE id_insecure_channel; +VALUE id_insecure_channel; /* grpc_rb_cChannel is the ruby class that proxies grpc_channel. */ -static VALUE grpc_rb_cChannel = Qnil; +VALUE grpc_rb_cChannel = Qnil; /* Used during the conversion of a hash to channel args during channel setup */ -static VALUE grpc_rb_cChannelArgs; +VALUE grpc_rb_cChannelArgs; + +typedef struct bg_watched_channel { + grpc_channel *channel; + struct bg_watched_channel *next; + int channel_destroyed; + int refcount; // must only be accessed under global_connection_polling_mu +} bg_watched_channel; /* grpc_rb_channel wraps a grpc_channel. */ typedef struct grpc_rb_channel { VALUE credentials; - /* The actual channel */ - grpc_channel *wrapped; - int request_safe_destroy; - int safe_to_destroy; - grpc_connectivity_state current_connectivity_state; - - int mu_init_done; - int abort_watch_connectivity_state; - gpr_mu channel_mu; - gpr_cv channel_cv; + /* The actual channel (protected in a wrapper to tell when it's safe to destroy) */ + bg_watched_channel *bg_wrapped; } grpc_rb_channel; -/* Forward declarations of functions involved in temporary fix to - * https://github.com/grpc/grpc/issues/9941 */ -static void grpc_rb_channel_try_register_connection_polling( - grpc_rb_channel *wrapper); -static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper); -static void *wait_until_channel_polling_thread_started_no_gil(void*); -static void wait_until_channel_polling_thread_started_unblocking_func(void*); +typedef enum { + CONTINUOUS_WATCH, + WATCH_STATE_API +} watch_state_op_type; + +typedef struct watch_state_op { + watch_state_op_type op_type; + // from event.success + union { + struct { + int success; + // has been called back due to a cq next call + int called_back; + } api_callback_args; + struct { + bg_watched_channel *bg; + } continuous_watch_callback_args; + } op; +} watch_state_op; + +bg_watched_channel *bg_watched_channel_list_head = NULL; + +void grpc_rb_channel_try_register_connection_polling(bg_watched_channel *bg); +void *wait_until_channel_polling_thread_started_no_gil(void*); +void wait_until_channel_polling_thread_started_unblocking_func(void*); +void *channel_init_try_register_connection_polling_without_gil(void *arg); + +typedef struct channel_init_try_register_stack { + grpc_channel *channel; + grpc_rb_channel *wrapper; +} channel_init_try_register_stack; + +grpc_completion_queue *channel_polling_cq; +gpr_mu global_connection_polling_mu; +gpr_cv global_connection_polling_cv; +int abort_channel_polling = 0; +int channel_polling_thread_started = 0; + +int bg_watched_channel_list_lookup(bg_watched_channel *bg); +bg_watched_channel *bg_watched_channel_list_create_and_add(grpc_channel *channel); +void bg_watched_channel_list_free_and_remove(bg_watched_channel *bg); +void run_poll_channels_loop_unblocking_func(void* arg); + +// Needs to be called under global_connection_polling_mu +void grpc_rb_channel_watch_connection_state_op_complete(watch_state_op* op, int success) { + GPR_ASSERT(!op->op.api_callback_args.called_back); + op->op.api_callback_args.called_back = 1; + op->op.api_callback_args.success = success; + // wake up the watch API call thats waiting on this op + gpr_cv_broadcast(&global_connection_polling_cv); +} + +/* Avoids destroying a channel twice. */ +void grpc_rb_channel_safe_destroy(bg_watched_channel *bg) { + gpr_mu_lock(&global_connection_polling_mu); + GPR_ASSERT(bg_watched_channel_list_lookup(bg)); + if (!bg->channel_destroyed) { + grpc_channel_destroy(bg->channel); + bg->channel_destroyed = 1; + } + bg->refcount--; + if (bg->refcount == 0) { + bg_watched_channel_list_free_and_remove(bg); + } + gpr_mu_unlock(&global_connection_polling_mu); +} -static grpc_completion_queue *channel_polling_cq; -static gpr_mu global_connection_polling_mu; -static gpr_cv global_connection_polling_cv; -static int abort_channel_polling = 0; -static int channel_polling_thread_started = 0; +void *channel_safe_destroy_without_gil(void *arg) { + grpc_rb_channel_safe_destroy((bg_watched_channel*)arg); + return NULL; +} /* Destroys Channel instances. */ -static void grpc_rb_channel_free(void *p) { +void grpc_rb_channel_free(void *p) { grpc_rb_channel *ch = NULL; if (p == NULL) { return; }; + gpr_log(GPR_DEBUG, "channel GC function called!"); ch = (grpc_rb_channel *)p; - if (ch->wrapped != NULL) { - grpc_rb_channel_safe_destroy(ch); - ch->wrapped = NULL; - } - - if (ch->mu_init_done) { - gpr_mu_destroy(&ch->channel_mu); - gpr_cv_destroy(&ch->channel_cv); + if (ch->bg_wrapped != NULL) { + /* assumption made here: it's ok to directly gpr_mu_lock the global + * connection polling mutex becuse we're in a finalizer, + * and we can count on this thread to not be interrupted. */ + grpc_rb_channel_safe_destroy(ch->bg_wrapped); + ch->bg_wrapped = NULL; } xfree(p); } /* Protects the mark object from GC */ -static void grpc_rb_channel_mark(void *p) { +void grpc_rb_channel_mark(void *p) { grpc_rb_channel *channel = NULL; if (p == NULL) { return; @@ -131,7 +187,7 @@ static void grpc_rb_channel_mark(void *p) { } } -static rb_data_type_t grpc_channel_data_type = {"grpc_channel", +rb_data_type_t grpc_channel_data_type = {"grpc_channel", {grpc_rb_channel_mark, grpc_rb_channel_free, GRPC_RB_MEMSIZE_UNAVAILABLE, @@ -144,9 +200,9 @@ static rb_data_type_t grpc_channel_data_type = {"grpc_channel", }; /* Allocates grpc_rb_channel instances. */ -static VALUE grpc_rb_channel_alloc(VALUE cls) { +VALUE grpc_rb_channel_alloc(VALUE cls) { grpc_rb_channel *wrapper = ALLOC(grpc_rb_channel); - wrapper->wrapped = NULL; + wrapper->bg_wrapped = NULL; wrapper->credentials = Qnil; return TypedData_Wrap_Struct(cls, &grpc_channel_data_type, wrapper); } @@ -159,7 +215,7 @@ static VALUE grpc_rb_channel_alloc(VALUE cls) { secure_channel = Channel:new("myhost:443", {'arg1': 'value1'}, creds) Creates channel instances. */ -static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { +VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { VALUE channel_args = Qnil; VALUE credentials = Qnil; VALUE target = Qnil; @@ -168,6 +224,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { grpc_channel_credentials *creds = NULL; char *target_chars = NULL; grpc_channel_args args; + channel_init_try_register_stack stack; MEMZERO(&args, grpc_channel_args, 1); grpc_ruby_once_init(); @@ -178,7 +235,6 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials); TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); - wrapper->mu_init_done = 0; target_chars = StringValueCStr(target); grpc_rb_hash_convert_to_channel_args(channel_args, &args); if (TYPE(credentials) == T_SYMBOL) { @@ -195,24 +251,10 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { } GPR_ASSERT(ch); - - wrapper->wrapped = ch; - - gpr_mu_init(&wrapper->channel_mu); - gpr_cv_init(&wrapper->channel_cv); - wrapper->mu_init_done = 1; - - gpr_mu_lock(&wrapper->channel_mu); - wrapper->abort_watch_connectivity_state = 0; - wrapper->current_connectivity_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0); - wrapper->safe_to_destroy = 0; - wrapper->request_safe_destroy = 0; - - gpr_cv_broadcast(&wrapper->channel_cv); - gpr_mu_unlock(&wrapper->channel_mu); - - - grpc_rb_channel_try_register_connection_polling(wrapper); + stack.channel = ch; + stack.wrapper = wrapper; + rb_thread_call_without_gvl( + channel_init_try_register_connection_polling_without_gil, &stack, NULL, NULL); if (args.args != NULL) { xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */ @@ -223,10 +265,32 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { return Qnil; } rb_ivar_set(self, id_target, target); - wrapper->wrapped = ch; return self; } +typedef struct get_state_stack { + grpc_channel *channel; + int try_to_connect; + int out; +} get_state_stack; + +void *get_state_without_gil(void *arg) { + get_state_stack *stack = (get_state_stack*)arg; + + gpr_mu_lock(&global_connection_polling_mu); + GPR_ASSERT(abort_channel_polling || channel_polling_thread_started); + if (abort_channel_polling) { + // the case in which the channel polling thread + // failed to start just always shows shutdown state. + stack->out = GRPC_CHANNEL_SHUTDOWN; + } else { + stack->out = grpc_channel_check_connectivity_state(stack->channel, stack->try_to_connect); + } + gpr_mu_unlock(&global_connection_polling_mu); + + return NULL; +} + /* call-seq: ch.connectivity_state -> state @@ -236,62 +300,66 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { constants defined in GRPC::Core::ConnectivityStates. It also tries to connect if the chennel is idle in the second form. */ -static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, +VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, VALUE self) { VALUE try_to_connect_param = Qfalse; int grpc_try_to_connect = 0; grpc_rb_channel *wrapper = NULL; - grpc_channel *ch = NULL; + get_state_stack stack; /* "01" == 0 mandatory args, 1 (try_to_connect) is optional */ rb_scan_args(argc, argv, "01", &try_to_connect_param); grpc_try_to_connect = RTEST(try_to_connect_param) ? 1 : 0; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); - ch = wrapper->wrapped; - if (ch == NULL) { + if (wrapper->bg_wrapped == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } - return LONG2NUM(grpc_channel_check_connectivity_state(wrapper->wrapped, grpc_try_to_connect)); + + stack.channel = wrapper->bg_wrapped->channel; + stack.try_to_connect = grpc_try_to_connect; + rb_thread_call_without_gvl(get_state_without_gil, &stack, NULL, NULL); + + return LONG2NUM(stack.out); } typedef struct watch_state_stack { - grpc_rb_channel *wrapper; + grpc_channel *channel; gpr_timespec deadline; int last_state; } watch_state_stack; -static void *watch_channel_state_without_gvl(void *arg) { +void *wait_for_watch_state_op_complete_without_gvl(void *arg) { watch_state_stack *stack = (watch_state_stack*)arg; - gpr_timespec deadline = stack->deadline; - grpc_rb_channel *wrapper = stack->wrapper; - int last_state = stack->last_state; - void *return_value = (void*)0; + watch_state_op *op = NULL; + void *success = (void*)0; - gpr_mu_lock(&wrapper->channel_mu); - while(wrapper->current_connectivity_state == last_state && - !wrapper->request_safe_destroy && - !wrapper->safe_to_destroy && - !wrapper->abort_watch_connectivity_state && - gpr_time_cmp(deadline, gpr_now(GPR_CLOCK_REALTIME)) > 0) { - gpr_cv_wait(&wrapper->channel_cv, &wrapper->channel_mu, deadline); + gpr_mu_lock(&global_connection_polling_mu); + // its unsafe to do a "watch" after "channel polling abort" because the cq has + // been shut down. + if (abort_channel_polling) { + gpr_mu_unlock(&global_connection_polling_mu); + return (void*)0; + } + op = gpr_zalloc(sizeof(watch_state_op)); + op->op_type = WATCH_STATE_API; + // one ref for this thread and another for the callback-running thread + grpc_channel_watch_connectivity_state( + stack->channel, stack->last_state, stack->deadline, channel_polling_cq, op); + + while(!op->op.api_callback_args.called_back) { + gpr_cv_wait(&global_connection_polling_cv, + &global_connection_polling_mu, + gpr_inf_future(GPR_CLOCK_REALTIME)); } - if (wrapper->current_connectivity_state != last_state) { - return_value = (void*)1; + if (op->op.api_callback_args.success) { + success = (void*)1; } - gpr_mu_unlock(&wrapper->channel_mu); - - return return_value; -} + gpr_free(op); + gpr_mu_unlock(&global_connection_polling_mu); -static void watch_channel_state_unblocking_func(void *arg) { - grpc_rb_channel *wrapper = (grpc_rb_channel*)arg; - gpr_log(GPR_DEBUG, "GRPC_RUBY: watch channel state unblocking func called"); - gpr_mu_lock(&wrapper->channel_mu); - wrapper->abort_watch_connectivity_state = 1; - gpr_cv_broadcast(&wrapper->channel_cv); - gpr_mu_unlock(&wrapper->channel_mu); + return success; } /* Wait until the channel's connectivity state becomes different from @@ -301,16 +369,16 @@ static void watch_channel_state_unblocking_func(void *arg) { * Returns false if "deadline" expires before the channel's connectivity * state changes from "last_state". * */ -static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, +VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, VALUE last_state, VALUE deadline) { grpc_rb_channel *wrapper = NULL; watch_state_stack stack; - void* out; + void* op_success = 0; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); - if (wrapper->wrapped == NULL) { + if (wrapper->bg_wrapped == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } @@ -320,26 +388,25 @@ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, return Qnil; } - stack.wrapper = wrapper; - stack.deadline = grpc_rb_time_timeval(deadline, 0); + stack.channel = wrapper->bg_wrapped->channel; + stack.deadline = grpc_rb_time_timeval(deadline, 0), stack.last_state = NUM2LONG(last_state); - out = rb_thread_call_without_gvl(watch_channel_state_without_gvl, &stack, watch_channel_state_unblocking_func, wrapper); - if (out) { - return Qtrue; - } - return Qfalse; + + op_success = rb_thread_call_without_gvl( + wait_for_watch_state_op_complete_without_gvl, &stack, run_poll_channels_loop_unblocking_func, NULL); + + return op_success ? Qtrue : Qfalse; } /* Create a call given a grpc_channel, in order to call method. The request is not sent until grpc_call_invoke is called. */ -static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, +VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, VALUE method, VALUE host, VALUE deadline) { VALUE res = Qnil; grpc_rb_channel *wrapper = NULL; grpc_call *call = NULL; grpc_call *parent_call = NULL; - grpc_channel *ch = NULL; grpc_completion_queue *cq = NULL; int flags = GRPC_PROPAGATE_DEFAULTS; grpc_slice method_slice; @@ -361,8 +428,7 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, cq = grpc_completion_queue_create(NULL); TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); - ch = wrapper->wrapped; - if (ch == NULL) { + if (wrapper->bg_wrapped == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } @@ -370,7 +436,7 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, method_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(method), RSTRING_LEN(method)); - call = grpc_channel_create_call(ch, parent_call, flags, cq, method_slice, + call = grpc_channel_create_call(wrapper->bg_wrapped->channel, parent_call, flags, cq, method_slice, host_slice_ptr, grpc_rb_time_timeval(deadline, /* absolute time */ 0), @@ -396,85 +462,132 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, } /* Closes the channel, calling it's destroy method */ -static VALUE grpc_rb_channel_destroy(VALUE self) { +/* Note this is an API-level call; a wrapped channel's finalizer doesn't call + * this */ +VALUE grpc_rb_channel_destroy(VALUE self) { grpc_rb_channel *wrapper = NULL; - grpc_channel *ch = NULL; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); - ch = wrapper->wrapped; - if (ch != NULL) { - grpc_rb_channel_safe_destroy(wrapper); - wrapper->wrapped = NULL; + if (wrapper->bg_wrapped != NULL) { + rb_thread_call_without_gvl( + channel_safe_destroy_without_gil, wrapper->bg_wrapped, NULL, NULL); + wrapper->bg_wrapped = NULL; } return Qnil; } /* Called to obtain the target that this channel accesses. */ -static VALUE grpc_rb_channel_get_target(VALUE self) { +VALUE grpc_rb_channel_get_target(VALUE self) { grpc_rb_channel *wrapper = NULL; VALUE res = Qnil; char *target = NULL; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); - target = grpc_channel_get_target(wrapper->wrapped); + target = grpc_channel_get_target(wrapper->bg_wrapped->channel); res = rb_str_new2(target); gpr_free(target); return res; } -// Either start polling channel connection state or signal that it's free to -// destroy. -// Not safe to call while a channel's connection state is polled. -static void grpc_rb_channel_try_register_connection_polling( - grpc_rb_channel *wrapper) { - grpc_connectivity_state conn_state; - gpr_timespec sleep_time = gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(20, GPR_TIMESPAN)); - - GPR_ASSERT(wrapper); - GPR_ASSERT(wrapper->wrapped); - gpr_mu_lock(&wrapper->channel_mu); - if (wrapper->request_safe_destroy) { - wrapper->safe_to_destroy = 1; - gpr_cv_broadcast(&wrapper->channel_cv); - gpr_mu_unlock(&wrapper->channel_mu); - return; +/* Needs to be called under global_connection_polling_mu */ +int bg_watched_channel_list_lookup(bg_watched_channel *target) { + bg_watched_channel *cur = bg_watched_channel_list_head; + + gpr_log(GPR_DEBUG, "check contains"); + while (cur != NULL) { + if (cur == target) { + return 1; + } + cur = cur->next; } - gpr_mu_lock(&global_connection_polling_mu); - GPR_ASSERT(channel_polling_thread_started || abort_channel_polling); - conn_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0); - if (conn_state != wrapper->current_connectivity_state) { - wrapper->current_connectivity_state = conn_state; - gpr_cv_broadcast(&wrapper->channel_cv); - } - // avoid posting work to the channel polling cq if it's been shutdown - if (!abort_channel_polling && conn_state != GRPC_CHANNEL_SHUTDOWN) { - grpc_channel_watch_connectivity_state( - wrapper->wrapped, conn_state, sleep_time, channel_polling_cq, wrapper); - } else { - wrapper->safe_to_destroy = 1; - gpr_cv_broadcast(&wrapper->channel_cv); + return 0; +} + +/* Needs to be called under global_connection_polling_mu */ +bg_watched_channel *bg_watched_channel_list_create_and_add(grpc_channel *channel) { + bg_watched_channel *watched = gpr_zalloc(sizeof(bg_watched_channel)); + + gpr_log(GPR_DEBUG, "add bg"); + watched->channel = channel; + watched->next = bg_watched_channel_list_head; + watched->refcount = 1; + bg_watched_channel_list_head = watched; + return watched; +} + +/* Needs to be called under global_connection_polling_mu */ +void bg_watched_channel_list_free_and_remove(bg_watched_channel *target) { + bg_watched_channel *bg = NULL; + + gpr_log(GPR_DEBUG, "remove bg"); + GPR_ASSERT(bg_watched_channel_list_lookup(target)); + GPR_ASSERT(target->channel_destroyed && target->refcount == 0); + if (bg_watched_channel_list_head == target) { + bg_watched_channel_list_head = target->next; + gpr_free(target); + return; + } + bg = bg_watched_channel_list_head; + while (bg != NULL && bg->next != NULL) { + if (bg->next == target) { + bg->next = bg->next->next; + gpr_free(target); + return; + } + bg = bg->next; } + GPR_ASSERT(0); +} + +/* Initialize a grpc_rb_channel's "protected grpc_channel" and try to push + * it onto the background thread for constant watches. */ +void *channel_init_try_register_connection_polling_without_gil(void *arg) { + channel_init_try_register_stack *stack = (channel_init_try_register_stack*)arg; + + gpr_mu_lock(&global_connection_polling_mu); + stack->wrapper->bg_wrapped = bg_watched_channel_list_create_and_add(stack->channel); + grpc_rb_channel_try_register_connection_polling(stack->wrapper->bg_wrapped); gpr_mu_unlock(&global_connection_polling_mu); - gpr_mu_unlock(&wrapper->channel_mu); + return NULL; } -// Note requires wrapper->wrapped, wrapper->channel_mu/cv initialized -static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper) { - gpr_mu_lock(&wrapper->channel_mu); - wrapper->request_safe_destroy = 1; +// Needs to be called under global_connection_poolling_mu +void grpc_rb_channel_try_register_connection_polling(bg_watched_channel *bg) { + grpc_connectivity_state conn_state; + watch_state_op *op = NULL; - while (!wrapper->safe_to_destroy) { - gpr_cv_wait(&wrapper->channel_cv, &wrapper->channel_mu, - gpr_inf_future(GPR_CLOCK_REALTIME)); + GPR_ASSERT(channel_polling_thread_started || abort_channel_polling); + + if (bg->refcount == 0) { + GPR_ASSERT(bg->channel_destroyed); + bg_watched_channel_list_free_and_remove(bg); + return; + } + GPR_ASSERT(bg->refcount == 1); + if (bg->channel_destroyed) { + GPR_ASSERT(abort_channel_polling); + return; + } + if (abort_channel_polling) { + return; } - GPR_ASSERT(wrapper->safe_to_destroy); - gpr_mu_unlock(&wrapper->channel_mu); - grpc_channel_destroy(wrapper->wrapped); + conn_state = grpc_channel_check_connectivity_state(bg->channel, 0); + if (conn_state == GRPC_CHANNEL_SHUTDOWN) { + return; + } + GPR_ASSERT(bg_watched_channel_list_lookup(bg)); + // prevent bg from being free'd by GC while background thread is watching it + bg->refcount++; + + op = gpr_zalloc(sizeof(watch_state_op)); + op->op_type = CONTINUOUS_WATCH; + op->op.continuous_watch_callback_args.bg = bg; + grpc_channel_watch_connectivity_state( + bg->channel, conn_state, gpr_inf_future(GPR_CLOCK_REALTIME), channel_polling_cq, op); } // Note this loop breaks out with a single call of @@ -483,8 +596,10 @@ static void grpc_rb_channel_safe_destroy(grpc_rb_channel *wrapper) { // indicates process shutdown. // In the worst case, this stops polling channel connectivity // early and falls back to current behavior. -static void *run_poll_channels_loop_no_gil(void *arg) { +void *run_poll_channels_loop_no_gil(void *arg) { grpc_event event; + watch_state_op *op = NULL; + bg_watched_channel *bg = NULL; (void)arg; gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_no_gil - begin"); @@ -500,9 +615,21 @@ static void *run_poll_channels_loop_no_gil(void *arg) { if (event.type == GRPC_QUEUE_SHUTDOWN) { break; } + gpr_mu_lock(&global_connection_polling_mu); if (event.type == GRPC_OP_COMPLETE) { - grpc_rb_channel_try_register_connection_polling((grpc_rb_channel *)event.tag); + op = (watch_state_op*)event.tag; + if (op->op_type == CONTINUOUS_WATCH) { + bg = (bg_watched_channel*)op->op.continuous_watch_callback_args.bg; + bg->refcount--; + grpc_rb_channel_try_register_connection_polling(bg); + gpr_free(op); + } else if(op->op_type == WATCH_STATE_API) { + grpc_rb_channel_watch_connection_state_op_complete((watch_state_op*)event.tag, event.success); + } else { + GPR_ASSERT(0); + } } + gpr_mu_unlock(&global_connection_polling_mu); } grpc_completion_queue_destroy(channel_polling_cq); gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_no_gil - exit connection polling loop"); @@ -510,17 +637,37 @@ static void *run_poll_channels_loop_no_gil(void *arg) { } // Notify the channel polling loop to cleanup and shutdown. -static void run_poll_channels_loop_unblocking_func(void *arg) { +void run_poll_channels_loop_unblocking_func(void *arg) { + bg_watched_channel *bg = NULL; (void)arg; + gpr_mu_lock(&global_connection_polling_mu); gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_unblocking_func - begin aborting connection polling"); + // early out after first time through + if (abort_channel_polling) { + gpr_mu_unlock(&global_connection_polling_mu); + return; + } abort_channel_polling = 1; + + // force pending watches to end by switching to shutdown state + bg = bg_watched_channel_list_head; + while(bg != NULL) { + if (!bg->channel_destroyed) { + grpc_channel_destroy(bg->channel); + bg->channel_destroyed = 1; + } + bg = bg->next; + } + grpc_completion_queue_shutdown(channel_polling_cq); + gpr_cv_broadcast(&global_connection_polling_cv); gpr_mu_unlock(&global_connection_polling_mu); + gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_unblocking_func - begin aborting connection polling 22222"); } // Poll channel connectivity states in background thread without the GIL. -static VALUE run_poll_channels_loop(VALUE arg) { +VALUE run_poll_channels_loop(VALUE arg) { (void)arg; gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop - create connection polling thread"); rb_thread_call_without_gvl(run_poll_channels_loop_no_gil, NULL, @@ -529,7 +676,7 @@ static VALUE run_poll_channels_loop(VALUE arg) { return Qnil; } -static void *wait_until_channel_polling_thread_started_no_gil(void *arg) { +void *wait_until_channel_polling_thread_started_no_gil(void *arg) { (void)arg; gpr_log(GPR_DEBUG, "GRPC_RUBY: wait for channel polling thread to start"); gpr_mu_lock(&global_connection_polling_mu); @@ -542,7 +689,7 @@ static void *wait_until_channel_polling_thread_started_no_gil(void *arg) { return NULL; } -static void wait_until_channel_polling_thread_started_unblocking_func(void* arg) { +void wait_until_channel_polling_thread_started_unblocking_func(void* arg) { (void)arg; gpr_mu_lock(&global_connection_polling_mu); gpr_log(GPR_DEBUG, "GRPC_RUBY: wait_until_channel_polling_thread_started_unblocking_func - begin aborting connection polling"); @@ -551,6 +698,16 @@ static void wait_until_channel_polling_thread_started_unblocking_func(void* arg) gpr_mu_unlock(&global_connection_polling_mu); } +static void *set_abort_channel_polling_without_gil(void *arg) { + (void)arg; + gpr_mu_lock(&global_connection_polling_mu); + abort_channel_polling = 1; + gpr_cv_broadcast(&global_connection_polling_cv); + gpr_mu_unlock(&global_connection_polling_mu); + return NULL; +} + + /* Temporary fix for * https://github.com/GoogleCloudPlatform/google-cloud-ruby/issues/899. * Transports in idle channels can get destroyed. Normally c-core re-connects, @@ -576,14 +733,11 @@ void grpc_rb_channel_polling_thread_start() { if (!RTEST(background_thread)) { gpr_log(GPR_DEBUG, "GRPC_RUBY: failed to spawn channel polling thread"); - gpr_mu_lock(&global_connection_polling_mu); - abort_channel_polling = 1; - gpr_cv_broadcast(&global_connection_polling_cv); - gpr_mu_unlock(&global_connection_polling_mu); + rb_thread_call_without_gvl(set_abort_channel_polling_without_gil, NULL, NULL, NULL); } } -static void Init_grpc_propagate_masks() { +void Init_grpc_propagate_masks() { /* Constants representing call propagation masks in grpc.h */ VALUE grpc_rb_mPropagateMasks = rb_define_module_under(grpc_rb_mGrpcCore, "PropagateMasks"); @@ -599,7 +753,7 @@ static void Init_grpc_propagate_masks() { UINT2NUM(GRPC_PROPAGATE_DEFAULTS)); } -static void Init_grpc_connectivity_states() { +void Init_grpc_connectivity_states() { /* Constants representing call propagation masks in grpc.h */ VALUE grpc_rb_mConnectivityStates = rb_define_module_under(grpc_rb_mGrpcCore, "ConnectivityStates"); @@ -658,5 +812,5 @@ void Init_grpc_channel() { grpc_channel *grpc_rb_get_wrapped_channel(VALUE v) { grpc_rb_channel *wrapper = NULL; TypedData_Get_Struct(v, grpc_rb_channel, &grpc_channel_data_type, wrapper); - return wrapper->wrapped; + return wrapper->bg_wrapped->channel; } diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c index fd75d2f691..9f3a81b1a8 100644 --- a/src/ruby/ext/grpc/rb_completion_queue.c +++ b/src/ruby/ext/grpc/rb_completion_queue.c @@ -71,12 +71,16 @@ static void *grpc_rb_completion_queue_pluck_no_gil(void *param) { } /* Helper function to free a completion queue. */ -void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq) { - /* Every function that adds an event to a queue also synchronously plucks - that event from the queue, and holds a reference to the Ruby object that - holds the queue, so we only get to this point if all of those functions - have completed, and the queue is empty */ +void grpc_rb_completion_queue_safe_destroy(grpc_completion_queue *cq) { + grpc_event ev; + grpc_completion_queue_shutdown(cq); + for(;;) { + ev = grpc_completion_queue_pluck(cq, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + if (ev.type == GRPC_QUEUE_SHUTDOWN) { + break; + } + } grpc_completion_queue_destroy(cq); } diff --git a/src/ruby/ext/grpc/rb_completion_queue.h b/src/ruby/ext/grpc/rb_completion_queue.h index aa9dc6416a..eb041b28df 100644 --- a/src/ruby/ext/grpc/rb_completion_queue.h +++ b/src/ruby/ext/grpc/rb_completion_queue.h @@ -38,7 +38,7 @@ #include -void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq); +void grpc_rb_completion_queue_safe_destroy(grpc_completion_queue *cq); /** * Makes the implementation of CompletionQueue#pluck available in other files diff --git a/src/ruby/ext/grpc/rb_event_thread.c b/src/ruby/ext/grpc/rb_event_thread.c index 9e85bbcfbf..f1a08a7b23 100644 --- a/src/ruby/ext/grpc/rb_event_thread.c +++ b/src/ruby/ext/grpc/rb_event_thread.c @@ -106,17 +106,17 @@ static void *grpc_rb_wait_for_event_no_gil(void *param) { grpc_rb_event *event = NULL; (void)param; gpr_mu_lock(&event_queue.mu); - while ((event = grpc_rb_event_queue_dequeue()) == NULL) { + while (!event_queue.abort) { + if ((event = grpc_rb_event_queue_dequeue()) != NULL) { + gpr_mu_unlock(&event_queue.mu); + return event; + } gpr_cv_wait(&event_queue.cv, &event_queue.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - if (event_queue.abort) { - gpr_mu_unlock(&event_queue.mu); - return NULL; - } } gpr_mu_unlock(&event_queue.mu); - return event; + return NULL; } static void grpc_rb_event_unblocking_func(void *arg) { diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 2286a99f24..2b0858c247 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -77,7 +77,7 @@ static void destroy_server(grpc_rb_server *server, gpr_timespec deadline) { gpr_inf_future(GPR_CLOCK_REALTIME), NULL); } grpc_server_destroy(server->wrapped); - grpc_rb_completion_queue_destroy(server->queue); + grpc_rb_completion_queue_safe_destroy(server->queue); server->wrapped = NULL; server->queue = NULL; } diff --git a/src/ruby/spec/channel_connection_spec.rb b/src/ruby/spec/channel_connection_spec.rb index 940d68b9b0..b3edec8f93 100644 --- a/src/ruby/spec/channel_connection_spec.rb +++ b/src/ruby/spec/channel_connection_spec.rb @@ -28,6 +28,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 'grpc' +require 'timeout' + +include Timeout +include GRPC::Core # A test message class EchoMsg @@ -62,7 +66,7 @@ end EchoStub = EchoService.rpc_stub_class def start_server(port = 0) - @srv = GRPC::RpcServer.new + @srv = GRPC::RpcServer.new(pool_size: 1) server_port = @srv.add_http2_port("localhost:#{port}", :this_port_is_insecure) @srv.handle(EchoService) @server_thd = Thread.new { @srv.run } @@ -138,4 +142,33 @@ describe 'channel connection behavior' do stop_server end + + it 'observably connects and reconnects to transient server' \ + ' when using the channel state API' do + timeout(180) do + port = start_server + ch = GRPC::Core::Channel.new("localhost:#{port}", {}, + :this_channel_is_insecure) + stop_server + + thds = [] + 50.times do + thds << Thread.new do + while ch.connectivity_state(true) != ConnectivityStates::READY + ch.watch_connectivity_state( + ConnectivityStates::READY, Time.now + 60) + break + end + end + end + + sleep 0.01 + + start_server(port) + + thds.each(&:join) + + stop_server + end + end end -- cgit v1.2.3 From 8d18c6edfbe675cbee6c425690c2e32b7dccba9d Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 15 May 2017 14:39:05 -0700 Subject: Fix race between destroying call after status and handling write failure --- src/node/ext/call.cc | 8 ++++++++ src/node/src/client.js | 12 ++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 8877995f8f..2cc9f63b65 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -721,6 +721,14 @@ NAN_METHOD(Call::StartBatch) { } Local callback_func = info[1].As(); Call *call = ObjectWrap::Unwrap(info.This()); + if (call->wrapped_call == NULL) { + /* This implies that the call has completed and has been destroyed. To emulate + * previous behavior, we should call the callback immediately with an error, + * as though the batch had failed in core */ + Local argv[] = {Nan::Error("The async function failed because the call has completed")}; + Nan::Call(callback_func, Nan::New(), 1, argv); + return; + } Local obj = Nan::To(info[0]).ToLocalChecked(); Local keys = Nan::GetOwnPropertyNames(obj).ToLocalChecked(); size_t nops = keys->Length(); diff --git a/src/node/src/client.js b/src/node/src/client.js index 1aaf35c16c..aa818349da 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -100,6 +100,12 @@ function _write(chunk, encoding, callback) { /* jshint validthis: true */ var batch = {}; var message; + var self = this; + if (this.writeFailed) { + /* Once a write fails, just call the callback immediately to let the caller + flush any pending writes. */ + callback(); + } try { message = this.serialize(chunk); } catch (e) { @@ -119,8 +125,10 @@ function _write(chunk, encoding, callback) { batch[grpc.opType.SEND_MESSAGE] = message; this.call.startBatch(batch, function(err, event) { if (err) { - // Something has gone wrong. Stop writing by failing to call callback - return; + /* Assume that the call is complete and that writing failed because a + status was received. In that case, set a flag to discard all future + writes */ + self.writeFailed = true; } callback(); }); -- cgit v1.2.3 From d822e2f5cf8d32efd0008c967551e994046b2d73 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 16 May 2017 12:53:57 -0700 Subject: Change write callback to asynchronous to avoid recursion --- src/node/src/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/src/client.js b/src/node/src/client.js index aa818349da..2073d3eea8 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -104,7 +104,7 @@ function _write(chunk, encoding, callback) { if (this.writeFailed) { /* Once a write fails, just call the callback immediately to let the caller flush any pending writes. */ - callback(); + setImmediate(callback); } try { message = this.serialize(chunk); -- cgit v1.2.3 From 0e2b6a2109fdb53884094de6c2395bd49fbf13e1 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Tue, 16 May 2017 17:16:05 -0700 Subject: remove debug prints --- src/ruby/ext/grpc/rb_channel.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 973a45adf5..c96dc672ce 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -161,7 +161,6 @@ void grpc_rb_channel_free(void *p) { if (p == NULL) { return; }; - gpr_log(GPR_DEBUG, "channel GC function called!"); ch = (grpc_rb_channel *)p; if (ch->bg_wrapped != NULL) { @@ -495,7 +494,6 @@ VALUE grpc_rb_channel_get_target(VALUE self) { int bg_watched_channel_list_lookup(bg_watched_channel *target) { bg_watched_channel *cur = bg_watched_channel_list_head; - gpr_log(GPR_DEBUG, "check contains"); while (cur != NULL) { if (cur == target) { return 1; @@ -510,7 +508,6 @@ int bg_watched_channel_list_lookup(bg_watched_channel *target) { bg_watched_channel *bg_watched_channel_list_create_and_add(grpc_channel *channel) { bg_watched_channel *watched = gpr_zalloc(sizeof(bg_watched_channel)); - gpr_log(GPR_DEBUG, "add bg"); watched->channel = channel; watched->next = bg_watched_channel_list_head; watched->refcount = 1; @@ -522,7 +519,6 @@ bg_watched_channel *bg_watched_channel_list_create_and_add(grpc_channel *channel void bg_watched_channel_list_free_and_remove(bg_watched_channel *target) { bg_watched_channel *bg = NULL; - gpr_log(GPR_DEBUG, "remove bg"); GPR_ASSERT(bg_watched_channel_list_lookup(target)); GPR_ASSERT(target->channel_destroyed && target->refcount == 0); if (bg_watched_channel_list_head == target) { -- cgit v1.2.3 From 7b3629e6c2570686701b4bdb6b171b219cbad06e Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 17 May 2017 00:29:10 -0700 Subject: fix lack-of-abort bug --- src/ruby/end2end/grpc_class_init_client.rb | 16 +++++++++++++--- src/ruby/ext/grpc/rb_channel.c | 12 +----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/ruby/end2end/grpc_class_init_client.rb b/src/ruby/end2end/grpc_class_init_client.rb index 8e46907368..62afc85b1d 100755 --- a/src/ruby/end2end/grpc_class_init_client.rb +++ b/src/ruby/end2end/grpc_class_init_client.rb @@ -106,9 +106,19 @@ def main return end - thd = Thread.new { test_proc.call } - test_proc.call - thd.join +# test_proc.call + + thds = [] + 100.times do + thds << Thread.new do + test_proc.call + sleep 10 + end + end + + #test_proc.call + raise "something" + thds.each(&:join) end main diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index c96dc672ce..748fe663ed 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -107,7 +107,6 @@ bg_watched_channel *bg_watched_channel_list_head = NULL; void grpc_rb_channel_try_register_connection_polling(bg_watched_channel *bg); void *wait_until_channel_polling_thread_started_no_gil(void*); -void wait_until_channel_polling_thread_started_unblocking_func(void*); void *channel_init_try_register_connection_polling_without_gil(void *arg); typedef struct channel_init_try_register_stack { @@ -228,7 +227,7 @@ VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { grpc_ruby_once_init(); rb_thread_call_without_gvl(wait_until_channel_polling_thread_started_no_gil, NULL, - wait_until_channel_polling_thread_started_unblocking_func, NULL); + run_poll_channels_loop_unblocking_func, NULL); /* "3" == 3 mandatory args */ rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials); @@ -685,15 +684,6 @@ void *wait_until_channel_polling_thread_started_no_gil(void *arg) { return NULL; } -void wait_until_channel_polling_thread_started_unblocking_func(void* arg) { - (void)arg; - gpr_mu_lock(&global_connection_polling_mu); - gpr_log(GPR_DEBUG, "GRPC_RUBY: wait_until_channel_polling_thread_started_unblocking_func - begin aborting connection polling"); - abort_channel_polling = 1; - gpr_cv_broadcast(&global_connection_polling_cv); - gpr_mu_unlock(&global_connection_polling_mu); -} - static void *set_abort_channel_polling_without_gil(void *arg) { (void)arg; gpr_mu_lock(&global_connection_polling_mu); -- cgit v1.2.3 From fd4cbb70774a943a790459c8ec54d8bb112a3ef2 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 17 May 2017 09:57:25 -0700 Subject: cleanup test --- src/ruby/end2end/grpc_class_init_client.rb | 57 ++++++++++++++++++++---------- src/ruby/end2end/grpc_class_init_driver.rb | 14 ++++---- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/ruby/end2end/grpc_class_init_client.rb b/src/ruby/end2end/grpc_class_init_client.rb index 62afc85b1d..d9c23c3835 100755 --- a/src/ruby/end2end/grpc_class_init_client.rb +++ b/src/ruby/end2end/grpc_class_init_client.rb @@ -60,6 +60,27 @@ def run_gc_stress_test(test_proc) construct_many(test_proc) end +def run_concurrency_stress_test(test_proc) + test_proc.call + + thds = [] + 100.times do + thds << Thread.new do + test_proc.call + end + end + + raise "something" +end + +# default (no gc_stress and no concurrency_stress) +def run_default_test(test_proc) + thd = Thread.new do + test_proc.call + end + test_proc.call +end + def get_test_proc(grpc_class) case grpc_class when 'channel' @@ -89,36 +110,34 @@ end def main grpc_class = '' - gc_stress = false + stress_test = '' OptionParser.new do |opts| opts.on('--grpc_class=P', String) do |p| grpc_class = p end - opts.on('--gc_stress=P') do |p| - gc_stress = p + opts.on('--stress_test=P') do |p| + stress_test = p end end.parse! test_proc = get_test_proc(grpc_class) - if gc_stress == 'true' + # the different test configs need to be ran + # in separate processes, since each one tests + # clean shutdown in a different way + case stress_test + when 'gc' + p 'run gc stress' run_gc_stress_test(test_proc) - return - end - -# test_proc.call - - thds = [] - 100.times do - thds << Thread.new do - test_proc.call - sleep 10 - end + when 'concurrency' + p 'run concurrency stress' + run_concurrency_stress_test(test_proc) + when '' + p 'run default' + run_default_test(test_proc) + else + fail "bad --stress_test=#{stress_test} param" end - - #test_proc.call - raise "something" - thds.each(&:join) end main diff --git a/src/ruby/end2end/grpc_class_init_driver.rb b/src/ruby/end2end/grpc_class_init_driver.rb index 0e330a493f..195da3cf9f 100755 --- a/src/ruby/end2end/grpc_class_init_driver.rb +++ b/src/ruby/end2end/grpc_class_init_driver.rb @@ -39,17 +39,17 @@ def main compression_options ) # there is room for false positives in this test, - # do 10 runs for each config to reduce these. - [true, false].each do |gc_stress| - 10.times do - native_grpc_classes.each do |grpc_class| + # do a few runs for each config + 4.times do + native_grpc_classes.each do |grpc_class| + ['', 'gc', 'concurrency'].each do |stress_test_type| STDERR.puts 'start client' this_dir = File.expand_path(File.dirname(__FILE__)) client_path = File.join(this_dir, 'grpc_class_init_client.rb') client_pid = Process.spawn(RbConfig.ruby, client_path, "--grpc_class=#{grpc_class}", - "--gc_stress=#{gc_stress}") + "--stress_test=#{stress_test_type}") begin Timeout.timeout(10) do Process.wait(client_pid) @@ -65,7 +65,9 @@ def main end client_exit_code = $CHILD_STATUS - if client_exit_code != 0 + # concurrency stress test type is expected to exit with a + # non-zero status due to an exception being raised + if client_exit_code != 0 and stress_test_type != 'concurrency' fail "client failed, exit code #{client_exit_code}" end end -- cgit v1.2.3 From 916893b618d602fef2ec1dbf9821611f67a7a1d3 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 17 May 2017 10:05:39 -0700 Subject: fix up the test --- src/ruby/end2end/grpc_class_init_client.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ruby/end2end/grpc_class_init_client.rb b/src/ruby/end2end/grpc_class_init_client.rb index d9c23c3835..464c42d07a 100755 --- a/src/ruby/end2end/grpc_class_init_client.rb +++ b/src/ruby/end2end/grpc_class_init_client.rb @@ -61,16 +61,15 @@ def run_gc_stress_test(test_proc) end def run_concurrency_stress_test(test_proc) - test_proc.call - - thds = [] 100.times do - thds << Thread.new do + Thread.new do test_proc.call end end - raise "something" + test_proc.call + + raise 'exception thrown while child thread initing class' end # default (no gc_stress and no concurrency_stress) -- cgit v1.2.3 From 5c6dda8639bd390565e794192ddfb15af0837c92 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 17 May 2017 13:08:34 -0700 Subject: fix tentative startup bug --- src/ruby/end2end/grpc_class_init_client.rb | 3 ++- src/ruby/end2end/grpc_class_init_driver.rb | 6 +++--- src/ruby/ext/grpc/rb_channel.c | 5 ++--- src/ruby/ext/grpc/rb_grpc.c | 21 +++++++++++++++++++-- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/ruby/end2end/grpc_class_init_client.rb b/src/ruby/end2end/grpc_class_init_client.rb index 464c42d07a..e73ca76850 100755 --- a/src/ruby/end2end/grpc_class_init_client.rb +++ b/src/ruby/end2end/grpc_class_init_client.rb @@ -69,7 +69,7 @@ def run_concurrency_stress_test(test_proc) test_proc.call - raise 'exception thrown while child thread initing class' + fail 'exception thrown while child thread initing class' end # default (no gc_stress and no concurrency_stress) @@ -78,6 +78,7 @@ def run_default_test(test_proc) test_proc.call end test_proc.call + thd.join end def get_test_proc(grpc_class) diff --git a/src/ruby/end2end/grpc_class_init_driver.rb b/src/ruby/end2end/grpc_class_init_driver.rb index 195da3cf9f..c65ed547c5 100755 --- a/src/ruby/end2end/grpc_class_init_driver.rb +++ b/src/ruby/end2end/grpc_class_init_driver.rb @@ -65,9 +65,9 @@ def main end client_exit_code = $CHILD_STATUS - # concurrency stress test type is expected to exit with a - # non-zero status due to an exception being raised - if client_exit_code != 0 and stress_test_type != 'concurrency' + # concurrency stress test type is expected to exit with a + # non-zero status due to an exception being raised + if client_exit_code != 0 && stress_test_type != 'concurrency' fail "client failed, exit code #{client_exit_code}" end end diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 748fe663ed..4e59174c3b 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -368,8 +368,8 @@ void *wait_for_watch_state_op_complete_without_gvl(void *arg) { * state changes from "last_state". * */ VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, - VALUE last_state, - VALUE deadline) { + VALUE last_state, + VALUE deadline) { grpc_rb_channel *wrapper = NULL; watch_state_stack stack; void* op_success = 0; @@ -693,7 +693,6 @@ static void *set_abort_channel_polling_without_gil(void *arg) { return NULL; } - /* Temporary fix for * https://github.com/GoogleCloudPlatform/google-cloud-ruby/issues/899. * Transports in idle channels can get destroyed. Normally c-core re-connects, diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c index 584b5dbc63..2a3b339102 100644 --- a/src/ruby/ext/grpc/rb_grpc.c +++ b/src/ruby/ext/grpc/rb_grpc.c @@ -42,6 +42,7 @@ #include #include +#include #include "rb_call.h" #include "rb_call_credentials.h" #include "rb_channel.h" @@ -295,11 +296,12 @@ static gpr_once g_once_init = GPR_ONCE_INIT; static void grpc_ruby_once_init_internal() { grpc_init(); - grpc_rb_event_queue_thread_start(); - grpc_rb_channel_polling_thread_start(); atexit(grpc_rb_shutdown); } +static VALUE bg_thread_init_rb_mu = Qundef; +static int bg_thread_init_done = 0; + void grpc_ruby_once_init() { /* ruby_vm_at_exit doesn't seem to be working. It would crash once every * blue moon, and some users are getting it repeatedly. See the discussions @@ -312,6 +314,18 @@ void grpc_ruby_once_init() { * schedule our initialization and destruction only once. */ gpr_once_init(&g_once_init, grpc_ruby_once_init_internal); + + // Avoid calling calling into ruby library (when creating threads here) + // in gpr_once_init. In general, it appears to be unsafe to call + // into the ruby library while holding a non-ruby mutex, because a gil yield + // could end up trying to lock onto that same mutex and deadlocking. + rb_mutex_lock(bg_thread_init_rb_mu); + if (!bg_thread_init_done) { + grpc_rb_event_queue_thread_start(); + grpc_rb_channel_polling_thread_start(); + bg_thread_init_done = 1; + } + rb_mutex_unlock(bg_thread_init_rb_mu); } void Init_grpc_c() { @@ -320,6 +334,9 @@ void Init_grpc_c() { return; } + bg_thread_init_rb_mu = rb_mutex_new(); + rb_global_variable(&bg_thread_init_rb_mu); + grpc_rb_mGRPC = rb_define_module("GRPC"); grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core"); grpc_rb_sNewServerRpc = -- cgit v1.2.3 From 7e44480614e2615821dabbece98989721d0cf6f4 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 17 May 2017 13:13:55 -0700 Subject: clang format --- src/ruby/ext/grpc/rb_channel.c | 138 +++++++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 60 deletions(-) diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 4e59174c3b..449c91a0f9 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -34,9 +34,9 @@ #include #include -#include "rb_grpc_imports.generated.h" #include "rb_byte_buffer.h" #include "rb_channel.h" +#include "rb_grpc_imports.generated.h" #include #include @@ -72,21 +72,19 @@ typedef struct bg_watched_channel { grpc_channel *channel; struct bg_watched_channel *next; int channel_destroyed; - int refcount; // must only be accessed under global_connection_polling_mu + int refcount; // must only be accessed under global_connection_polling_mu } bg_watched_channel; /* grpc_rb_channel wraps a grpc_channel. */ typedef struct grpc_rb_channel { VALUE credentials; - /* The actual channel (protected in a wrapper to tell when it's safe to destroy) */ + /* The actual channel (protected in a wrapper to tell when it's safe to + * destroy) */ bg_watched_channel *bg_wrapped; } grpc_rb_channel; -typedef enum { - CONTINUOUS_WATCH, - WATCH_STATE_API -} watch_state_op_type; +typedef enum { CONTINUOUS_WATCH, WATCH_STATE_API } watch_state_op_type; typedef struct watch_state_op { watch_state_op_type op_type; @@ -106,7 +104,7 @@ typedef struct watch_state_op { bg_watched_channel *bg_watched_channel_list_head = NULL; void grpc_rb_channel_try_register_connection_polling(bg_watched_channel *bg); -void *wait_until_channel_polling_thread_started_no_gil(void*); +void *wait_until_channel_polling_thread_started_no_gil(void *); void *channel_init_try_register_connection_polling_without_gil(void *arg); typedef struct channel_init_try_register_stack { @@ -121,12 +119,14 @@ int abort_channel_polling = 0; int channel_polling_thread_started = 0; int bg_watched_channel_list_lookup(bg_watched_channel *bg); -bg_watched_channel *bg_watched_channel_list_create_and_add(grpc_channel *channel); +bg_watched_channel *bg_watched_channel_list_create_and_add( + grpc_channel *channel); void bg_watched_channel_list_free_and_remove(bg_watched_channel *bg); -void run_poll_channels_loop_unblocking_func(void* arg); +void run_poll_channels_loop_unblocking_func(void *arg); // Needs to be called under global_connection_polling_mu -void grpc_rb_channel_watch_connection_state_op_complete(watch_state_op* op, int success) { +void grpc_rb_channel_watch_connection_state_op_complete(watch_state_op *op, + int success) { GPR_ASSERT(!op->op.api_callback_args.called_back); op->op.api_callback_args.called_back = 1; op->op.api_callback_args.success = success; @@ -150,7 +150,7 @@ void grpc_rb_channel_safe_destroy(bg_watched_channel *bg) { } void *channel_safe_destroy_without_gil(void *arg) { - grpc_rb_channel_safe_destroy((bg_watched_channel*)arg); + grpc_rb_channel_safe_destroy((bg_watched_channel *)arg); return NULL; } @@ -186,14 +186,14 @@ void grpc_rb_channel_mark(void *p) { } rb_data_type_t grpc_channel_data_type = {"grpc_channel", - {grpc_rb_channel_mark, - grpc_rb_channel_free, - GRPC_RB_MEMSIZE_UNAVAILABLE, - {NULL, NULL}}, - NULL, - NULL, + {grpc_rb_channel_mark, + grpc_rb_channel_free, + GRPC_RB_MEMSIZE_UNAVAILABLE, + {NULL, NULL}}, + NULL, + NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY - RUBY_TYPED_FREE_IMMEDIATELY + RUBY_TYPED_FREE_IMMEDIATELY #endif }; @@ -226,8 +226,9 @@ VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { MEMZERO(&args, grpc_channel_args, 1); grpc_ruby_once_init(); - rb_thread_call_without_gvl(wait_until_channel_polling_thread_started_no_gil, NULL, - run_poll_channels_loop_unblocking_func, NULL); + rb_thread_call_without_gvl(wait_until_channel_polling_thread_started_no_gil, + NULL, run_poll_channels_loop_unblocking_func, + NULL); /* "3" == 3 mandatory args */ rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials); @@ -252,7 +253,8 @@ VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { stack.channel = ch; stack.wrapper = wrapper; rb_thread_call_without_gvl( - channel_init_try_register_connection_polling_without_gil, &stack, NULL, NULL); + channel_init_try_register_connection_polling_without_gil, &stack, NULL, + NULL); if (args.args != NULL) { xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */ @@ -273,7 +275,7 @@ typedef struct get_state_stack { } get_state_stack; void *get_state_without_gil(void *arg) { - get_state_stack *stack = (get_state_stack*)arg; + get_state_stack *stack = (get_state_stack *)arg; gpr_mu_lock(&global_connection_polling_mu); GPR_ASSERT(abort_channel_polling || channel_polling_thread_started); @@ -282,7 +284,8 @@ void *get_state_without_gil(void *arg) { // failed to start just always shows shutdown state. stack->out = GRPC_CHANNEL_SHUTDOWN; } else { - stack->out = grpc_channel_check_connectivity_state(stack->channel, stack->try_to_connect); + stack->out = grpc_channel_check_connectivity_state(stack->channel, + stack->try_to_connect); } gpr_mu_unlock(&global_connection_polling_mu); @@ -299,7 +302,7 @@ void *get_state_without_gil(void *arg) { It also tries to connect if the chennel is idle in the second form. */ VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, - VALUE self) { + VALUE self) { VALUE try_to_connect_param = Qfalse; int grpc_try_to_connect = 0; grpc_rb_channel *wrapper = NULL; @@ -329,30 +332,30 @@ typedef struct watch_state_stack { } watch_state_stack; void *wait_for_watch_state_op_complete_without_gvl(void *arg) { - watch_state_stack *stack = (watch_state_stack*)arg; + watch_state_stack *stack = (watch_state_stack *)arg; watch_state_op *op = NULL; - void *success = (void*)0; + void *success = (void *)0; gpr_mu_lock(&global_connection_polling_mu); // its unsafe to do a "watch" after "channel polling abort" because the cq has // been shut down. if (abort_channel_polling) { gpr_mu_unlock(&global_connection_polling_mu); - return (void*)0; + return (void *)0; } op = gpr_zalloc(sizeof(watch_state_op)); op->op_type = WATCH_STATE_API; // one ref for this thread and another for the callback-running thread - grpc_channel_watch_connectivity_state( - stack->channel, stack->last_state, stack->deadline, channel_polling_cq, op); + grpc_channel_watch_connectivity_state(stack->channel, stack->last_state, + stack->deadline, channel_polling_cq, + op); - while(!op->op.api_callback_args.called_back) { - gpr_cv_wait(&global_connection_polling_cv, - &global_connection_polling_mu, + while (!op->op.api_callback_args.called_back) { + gpr_cv_wait(&global_connection_polling_cv, &global_connection_polling_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } if (op->op.api_callback_args.success) { - success = (void*)1; + success = (void *)1; } gpr_free(op); gpr_mu_unlock(&global_connection_polling_mu); @@ -367,12 +370,11 @@ void *wait_for_watch_state_op_complete_without_gvl(void *arg) { * Returns false if "deadline" expires before the channel's connectivity * state changes from "last_state". * */ -VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, - VALUE last_state, +VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, VALUE last_state, VALUE deadline) { grpc_rb_channel *wrapper = NULL; watch_state_stack stack; - void* op_success = 0; + void *op_success = 0; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); @@ -382,7 +384,9 @@ VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, } if (!FIXNUM_P(last_state)) { - rb_raise(rb_eTypeError, "bad type for last_state. want a GRPC::Core::ChannelState constant"); + rb_raise( + rb_eTypeError, + "bad type for last_state. want a GRPC::Core::ChannelState constant"); return Qnil; } @@ -391,7 +395,8 @@ VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, stack.last_state = NUM2LONG(last_state); op_success = rb_thread_call_without_gvl( - wait_for_watch_state_op_complete_without_gvl, &stack, run_poll_channels_loop_unblocking_func, NULL); + wait_for_watch_state_op_complete_without_gvl, &stack, + run_poll_channels_loop_unblocking_func, NULL); return op_success ? Qtrue : Qfalse; } @@ -399,8 +404,7 @@ VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, /* Create a call given a grpc_channel, in order to call method. The request is not sent until grpc_call_invoke is called. */ VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, - VALUE method, VALUE host, - VALUE deadline) { + VALUE method, VALUE host, VALUE deadline) { VALUE res = Qnil; grpc_rb_channel *wrapper = NULL; grpc_call *call = NULL; @@ -434,8 +438,8 @@ VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, method_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(method), RSTRING_LEN(method)); - call = grpc_channel_create_call(wrapper->bg_wrapped->channel, parent_call, flags, cq, method_slice, - host_slice_ptr, + call = grpc_channel_create_call(wrapper->bg_wrapped->channel, parent_call, + flags, cq, method_slice, host_slice_ptr, grpc_rb_time_timeval(deadline, /* absolute time */ 0), NULL); @@ -467,8 +471,8 @@ VALUE grpc_rb_channel_destroy(VALUE self) { TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); if (wrapper->bg_wrapped != NULL) { - rb_thread_call_without_gvl( - channel_safe_destroy_without_gil, wrapper->bg_wrapped, NULL, NULL); + rb_thread_call_without_gvl(channel_safe_destroy_without_gil, + wrapper->bg_wrapped, NULL, NULL); wrapper->bg_wrapped = NULL; } @@ -504,7 +508,8 @@ int bg_watched_channel_list_lookup(bg_watched_channel *target) { } /* Needs to be called under global_connection_polling_mu */ -bg_watched_channel *bg_watched_channel_list_create_and_add(grpc_channel *channel) { +bg_watched_channel *bg_watched_channel_list_create_and_add( + grpc_channel *channel) { bg_watched_channel *watched = gpr_zalloc(sizeof(bg_watched_channel)); watched->channel = channel; @@ -540,10 +545,12 @@ void bg_watched_channel_list_free_and_remove(bg_watched_channel *target) { /* Initialize a grpc_rb_channel's "protected grpc_channel" and try to push * it onto the background thread for constant watches. */ void *channel_init_try_register_connection_polling_without_gil(void *arg) { - channel_init_try_register_stack *stack = (channel_init_try_register_stack*)arg; + channel_init_try_register_stack *stack = + (channel_init_try_register_stack *)arg; gpr_mu_lock(&global_connection_polling_mu); - stack->wrapper->bg_wrapped = bg_watched_channel_list_create_and_add(stack->channel); + stack->wrapper->bg_wrapped = + bg_watched_channel_list_create_and_add(stack->channel); grpc_rb_channel_try_register_connection_polling(stack->wrapper->bg_wrapped); gpr_mu_unlock(&global_connection_polling_mu); return NULL; @@ -581,8 +588,9 @@ void grpc_rb_channel_try_register_connection_polling(bg_watched_channel *bg) { op = gpr_zalloc(sizeof(watch_state_op)); op->op_type = CONTINUOUS_WATCH; op->op.continuous_watch_callback_args.bg = bg; - grpc_channel_watch_connectivity_state( - bg->channel, conn_state, gpr_inf_future(GPR_CLOCK_REALTIME), channel_polling_cq, op); + grpc_channel_watch_connectivity_state(bg->channel, conn_state, + gpr_inf_future(GPR_CLOCK_REALTIME), + channel_polling_cq, op); } // Note this loop breaks out with a single call of @@ -612,14 +620,15 @@ void *run_poll_channels_loop_no_gil(void *arg) { } gpr_mu_lock(&global_connection_polling_mu); if (event.type == GRPC_OP_COMPLETE) { - op = (watch_state_op*)event.tag; + op = (watch_state_op *)event.tag; if (op->op_type == CONTINUOUS_WATCH) { - bg = (bg_watched_channel*)op->op.continuous_watch_callback_args.bg; + bg = (bg_watched_channel *)op->op.continuous_watch_callback_args.bg; bg->refcount--; grpc_rb_channel_try_register_connection_polling(bg); gpr_free(op); - } else if(op->op_type == WATCH_STATE_API) { - grpc_rb_channel_watch_connection_state_op_complete((watch_state_op*)event.tag, event.success); + } else if (op->op_type == WATCH_STATE_API) { + grpc_rb_channel_watch_connection_state_op_complete( + (watch_state_op *)event.tag, event.success); } else { GPR_ASSERT(0); } @@ -627,7 +636,9 @@ void *run_poll_channels_loop_no_gil(void *arg) { gpr_mu_unlock(&global_connection_polling_mu); } grpc_completion_queue_destroy(channel_polling_cq); - gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_no_gil - exit connection polling loop"); + gpr_log(GPR_DEBUG, + "GRPC_RUBY: run_poll_channels_loop_no_gil - exit connection polling " + "loop"); return NULL; } @@ -637,7 +648,9 @@ void run_poll_channels_loop_unblocking_func(void *arg) { (void)arg; gpr_mu_lock(&global_connection_polling_mu); - gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_unblocking_func - begin aborting connection polling"); + gpr_log(GPR_DEBUG, + "GRPC_RUBY: run_poll_channels_loop_unblocking_func - begin aborting " + "connection polling"); // early out after first time through if (abort_channel_polling) { gpr_mu_unlock(&global_connection_polling_mu); @@ -647,7 +660,7 @@ void run_poll_channels_loop_unblocking_func(void *arg) { // force pending watches to end by switching to shutdown state bg = bg_watched_channel_list_head; - while(bg != NULL) { + while (bg != NULL) { if (!bg->channel_destroyed) { grpc_channel_destroy(bg->channel); bg->channel_destroyed = 1; @@ -658,13 +671,17 @@ void run_poll_channels_loop_unblocking_func(void *arg) { grpc_completion_queue_shutdown(channel_polling_cq); gpr_cv_broadcast(&global_connection_polling_cv); gpr_mu_unlock(&global_connection_polling_mu); - gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop_unblocking_func - begin aborting connection polling 22222"); + gpr_log(GPR_DEBUG, + "GRPC_RUBY: run_poll_channels_loop_unblocking_func - end aborting " + "connection polling"); } // Poll channel connectivity states in background thread without the GIL. VALUE run_poll_channels_loop(VALUE arg) { (void)arg; - gpr_log(GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop - create connection polling thread"); + gpr_log( + GPR_DEBUG, + "GRPC_RUBY: run_poll_channels_loop - create connection polling thread"); rb_thread_call_without_gvl(run_poll_channels_loop_no_gil, NULL, run_poll_channels_loop_unblocking_func, NULL); @@ -718,7 +735,8 @@ void grpc_rb_channel_polling_thread_start() { if (!RTEST(background_thread)) { gpr_log(GPR_DEBUG, "GRPC_RUBY: failed to spawn channel polling thread"); - rb_thread_call_without_gvl(set_abort_channel_polling_without_gil, NULL, NULL, NULL); + rb_thread_call_without_gvl(set_abort_channel_polling_without_gil, NULL, + NULL, NULL); } } -- cgit v1.2.3 From 032f398543676818b3e0761f8bdd899c8c3616eb Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 17 May 2017 13:22:55 -0700 Subject: cleanup --- src/ruby/ext/grpc/rb_call.c | 2 +- src/ruby/ext/grpc/rb_channel.c | 132 ++++++++++++++++--------------- src/ruby/ext/grpc/rb_completion_queue.c | 14 ++-- src/ruby/ext/grpc/rb_completion_queue.h | 2 +- src/ruby/ext/grpc/rb_grpc.c | 1 - src/ruby/ext/grpc/rb_server.c | 2 +- src/ruby/spec/channel_connection_spec.rb | 3 +- 7 files changed, 79 insertions(+), 77 deletions(-) diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c index 6cb71870f5..344cb941ff 100644 --- a/src/ruby/ext/grpc/rb_call.c +++ b/src/ruby/ext/grpc/rb_call.c @@ -103,7 +103,7 @@ static void destroy_call(grpc_rb_call *call) { if (call->wrapped != NULL) { grpc_call_destroy(call->wrapped); call->wrapped = NULL; - grpc_rb_completion_queue_safe_destroy(call->queue); + grpc_rb_completion_queue_destroy(call->queue); call->queue = NULL; } } diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 449c91a0f9..e02dd0805d 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -52,27 +52,28 @@ /* id_channel is the name of the hidden ivar that preserves a reference to the * channel on a call, so that calls are not GCed before their channel. */ -ID id_channel; +static ID id_channel; /* id_target is the name of the hidden ivar that preserves a reference to the * target string used to create the call, preserved so that it does not get * GCed before the channel */ -ID id_target; +static ID id_target; /* id_insecure_channel is used to indicate that a channel is insecure */ -VALUE id_insecure_channel; +static VALUE id_insecure_channel; /* grpc_rb_cChannel is the ruby class that proxies grpc_channel. */ -VALUE grpc_rb_cChannel = Qnil; +static VALUE grpc_rb_cChannel = Qnil; /* Used during the conversion of a hash to channel args during channel setup */ -VALUE grpc_rb_cChannelArgs; +static VALUE grpc_rb_cChannelArgs; typedef struct bg_watched_channel { grpc_channel *channel; + // these fields must only be accessed under global_connection_polling_mu struct bg_watched_channel *next; int channel_destroyed; - int refcount; // must only be accessed under global_connection_polling_mu + int refcount; } bg_watched_channel; /* grpc_rb_channel wraps a grpc_channel. */ @@ -101,32 +102,34 @@ typedef struct watch_state_op { } op; } watch_state_op; -bg_watched_channel *bg_watched_channel_list_head = NULL; +static bg_watched_channel *bg_watched_channel_list_head = NULL; -void grpc_rb_channel_try_register_connection_polling(bg_watched_channel *bg); -void *wait_until_channel_polling_thread_started_no_gil(void *); -void *channel_init_try_register_connection_polling_without_gil(void *arg); +static void grpc_rb_channel_try_register_connection_polling( + bg_watched_channel *bg); +static void *wait_until_channel_polling_thread_started_no_gil(void *); +static void *channel_init_try_register_connection_polling_without_gil( + void *arg); typedef struct channel_init_try_register_stack { grpc_channel *channel; grpc_rb_channel *wrapper; } channel_init_try_register_stack; -grpc_completion_queue *channel_polling_cq; -gpr_mu global_connection_polling_mu; -gpr_cv global_connection_polling_cv; -int abort_channel_polling = 0; -int channel_polling_thread_started = 0; +static grpc_completion_queue *channel_polling_cq; +static gpr_mu global_connection_polling_mu; +static gpr_cv global_connection_polling_cv; +static int abort_channel_polling = 0; +static int channel_polling_thread_started = 0; -int bg_watched_channel_list_lookup(bg_watched_channel *bg); -bg_watched_channel *bg_watched_channel_list_create_and_add( +static int bg_watched_channel_list_lookup(bg_watched_channel *bg); +static bg_watched_channel *bg_watched_channel_list_create_and_add( grpc_channel *channel); -void bg_watched_channel_list_free_and_remove(bg_watched_channel *bg); -void run_poll_channels_loop_unblocking_func(void *arg); +static void bg_watched_channel_list_free_and_remove(bg_watched_channel *bg); +static void run_poll_channels_loop_unblocking_func(void *arg); // Needs to be called under global_connection_polling_mu -void grpc_rb_channel_watch_connection_state_op_complete(watch_state_op *op, - int success) { +static void grpc_rb_channel_watch_connection_state_op_complete( + watch_state_op *op, int success) { GPR_ASSERT(!op->op.api_callback_args.called_back); op->op.api_callback_args.called_back = 1; op->op.api_callback_args.success = success; @@ -135,7 +138,7 @@ void grpc_rb_channel_watch_connection_state_op_complete(watch_state_op *op, } /* Avoids destroying a channel twice. */ -void grpc_rb_channel_safe_destroy(bg_watched_channel *bg) { +static void grpc_rb_channel_safe_destroy(bg_watched_channel *bg) { gpr_mu_lock(&global_connection_polling_mu); GPR_ASSERT(bg_watched_channel_list_lookup(bg)); if (!bg->channel_destroyed) { @@ -149,13 +152,13 @@ void grpc_rb_channel_safe_destroy(bg_watched_channel *bg) { gpr_mu_unlock(&global_connection_polling_mu); } -void *channel_safe_destroy_without_gil(void *arg) { +static void *channel_safe_destroy_without_gil(void *arg) { grpc_rb_channel_safe_destroy((bg_watched_channel *)arg); return NULL; } /* Destroys Channel instances. */ -void grpc_rb_channel_free(void *p) { +static void grpc_rb_channel_free(void *p) { grpc_rb_channel *ch = NULL; if (p == NULL) { return; @@ -165,7 +168,8 @@ void grpc_rb_channel_free(void *p) { if (ch->bg_wrapped != NULL) { /* assumption made here: it's ok to directly gpr_mu_lock the global * connection polling mutex becuse we're in a finalizer, - * and we can count on this thread to not be interrupted. */ + * and we can count on this thread to not be interrupted or + * yield the gil. */ grpc_rb_channel_safe_destroy(ch->bg_wrapped); ch->bg_wrapped = NULL; } @@ -174,7 +178,7 @@ void grpc_rb_channel_free(void *p) { } /* Protects the mark object from GC */ -void grpc_rb_channel_mark(void *p) { +static void grpc_rb_channel_mark(void *p) { grpc_rb_channel *channel = NULL; if (p == NULL) { return; @@ -185,20 +189,20 @@ void grpc_rb_channel_mark(void *p) { } } -rb_data_type_t grpc_channel_data_type = {"grpc_channel", - {grpc_rb_channel_mark, - grpc_rb_channel_free, - GRPC_RB_MEMSIZE_UNAVAILABLE, - {NULL, NULL}}, - NULL, - NULL, +static rb_data_type_t grpc_channel_data_type = {"grpc_channel", + {grpc_rb_channel_mark, + grpc_rb_channel_free, + GRPC_RB_MEMSIZE_UNAVAILABLE, + {NULL, NULL}}, + NULL, + NULL, #ifdef RUBY_TYPED_FREE_IMMEDIATELY - RUBY_TYPED_FREE_IMMEDIATELY + RUBY_TYPED_FREE_IMMEDIATELY #endif }; /* Allocates grpc_rb_channel instances. */ -VALUE grpc_rb_channel_alloc(VALUE cls) { +static VALUE grpc_rb_channel_alloc(VALUE cls) { grpc_rb_channel *wrapper = ALLOC(grpc_rb_channel); wrapper->bg_wrapped = NULL; wrapper->credentials = Qnil; @@ -213,7 +217,7 @@ VALUE grpc_rb_channel_alloc(VALUE cls) { secure_channel = Channel:new("myhost:443", {'arg1': 'value1'}, creds) Creates channel instances. */ -VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { +static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { VALUE channel_args = Qnil; VALUE credentials = Qnil; VALUE target = Qnil; @@ -274,13 +278,15 @@ typedef struct get_state_stack { int out; } get_state_stack; -void *get_state_without_gil(void *arg) { +static void *get_state_without_gil(void *arg) { get_state_stack *stack = (get_state_stack *)arg; gpr_mu_lock(&global_connection_polling_mu); GPR_ASSERT(abort_channel_polling || channel_polling_thread_started); if (abort_channel_polling) { - // the case in which the channel polling thread + // Assume that this channel has been destroyed by the + // background thread. + // The case in which the channel polling thread // failed to start just always shows shutdown state. stack->out = GRPC_CHANNEL_SHUTDOWN; } else { @@ -301,16 +307,14 @@ void *get_state_without_gil(void *arg) { constants defined in GRPC::Core::ConnectivityStates. It also tries to connect if the chennel is idle in the second form. */ -VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, - VALUE self) { +static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, + VALUE self) { VALUE try_to_connect_param = Qfalse; - int grpc_try_to_connect = 0; grpc_rb_channel *wrapper = NULL; get_state_stack stack; /* "01" == 0 mandatory args, 1 (try_to_connect) is optional */ rb_scan_args(argc, argv, "01", &try_to_connect_param); - grpc_try_to_connect = RTEST(try_to_connect_param) ? 1 : 0; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); if (wrapper->bg_wrapped == NULL) { @@ -319,7 +323,7 @@ VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, } stack.channel = wrapper->bg_wrapped->channel; - stack.try_to_connect = grpc_try_to_connect; + stack.try_to_connect = RTEST(try_to_connect_param) ? 1 : 0; rb_thread_call_without_gvl(get_state_without_gil, &stack, NULL, NULL); return LONG2NUM(stack.out); @@ -331,7 +335,7 @@ typedef struct watch_state_stack { int last_state; } watch_state_stack; -void *wait_for_watch_state_op_complete_without_gvl(void *arg) { +static void *wait_for_watch_state_op_complete_without_gvl(void *arg) { watch_state_stack *stack = (watch_state_stack *)arg; watch_state_op *op = NULL; void *success = (void *)0; @@ -345,7 +349,6 @@ void *wait_for_watch_state_op_complete_without_gvl(void *arg) { } op = gpr_zalloc(sizeof(watch_state_op)); op->op_type = WATCH_STATE_API; - // one ref for this thread and another for the callback-running thread grpc_channel_watch_connectivity_state(stack->channel, stack->last_state, stack->deadline, channel_polling_cq, op); @@ -370,8 +373,9 @@ void *wait_for_watch_state_op_complete_without_gvl(void *arg) { * Returns false if "deadline" expires before the channel's connectivity * state changes from "last_state". * */ -VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, VALUE last_state, - VALUE deadline) { +static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, + VALUE last_state, + VALUE deadline) { grpc_rb_channel *wrapper = NULL; watch_state_stack stack; void *op_success = 0; @@ -403,8 +407,9 @@ VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, VALUE last_state, /* Create a call given a grpc_channel, in order to call method. The request is not sent until grpc_call_invoke is called. */ -VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, - VALUE method, VALUE host, VALUE deadline) { +static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, + VALUE method, VALUE host, + VALUE deadline) { VALUE res = Qnil; grpc_rb_channel *wrapper = NULL; grpc_call *call = NULL; @@ -466,7 +471,7 @@ VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, /* Closes the channel, calling it's destroy method */ /* Note this is an API-level call; a wrapped channel's finalizer doesn't call * this */ -VALUE grpc_rb_channel_destroy(VALUE self) { +static VALUE grpc_rb_channel_destroy(VALUE self) { grpc_rb_channel *wrapper = NULL; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); @@ -480,7 +485,7 @@ VALUE grpc_rb_channel_destroy(VALUE self) { } /* Called to obtain the target that this channel accesses. */ -VALUE grpc_rb_channel_get_target(VALUE self) { +static VALUE grpc_rb_channel_get_target(VALUE self) { grpc_rb_channel *wrapper = NULL; VALUE res = Qnil; char *target = NULL; @@ -494,7 +499,7 @@ VALUE grpc_rb_channel_get_target(VALUE self) { } /* Needs to be called under global_connection_polling_mu */ -int bg_watched_channel_list_lookup(bg_watched_channel *target) { +static int bg_watched_channel_list_lookup(bg_watched_channel *target) { bg_watched_channel *cur = bg_watched_channel_list_head; while (cur != NULL) { @@ -508,7 +513,7 @@ int bg_watched_channel_list_lookup(bg_watched_channel *target) { } /* Needs to be called under global_connection_polling_mu */ -bg_watched_channel *bg_watched_channel_list_create_and_add( +static bg_watched_channel *bg_watched_channel_list_create_and_add( grpc_channel *channel) { bg_watched_channel *watched = gpr_zalloc(sizeof(bg_watched_channel)); @@ -520,7 +525,8 @@ bg_watched_channel *bg_watched_channel_list_create_and_add( } /* Needs to be called under global_connection_polling_mu */ -void bg_watched_channel_list_free_and_remove(bg_watched_channel *target) { +static void bg_watched_channel_list_free_and_remove( + bg_watched_channel *target) { bg_watched_channel *bg = NULL; GPR_ASSERT(bg_watched_channel_list_lookup(target)); @@ -544,7 +550,8 @@ void bg_watched_channel_list_free_and_remove(bg_watched_channel *target) { /* Initialize a grpc_rb_channel's "protected grpc_channel" and try to push * it onto the background thread for constant watches. */ -void *channel_init_try_register_connection_polling_without_gil(void *arg) { +static void *channel_init_try_register_connection_polling_without_gil( + void *arg) { channel_init_try_register_stack *stack = (channel_init_try_register_stack *)arg; @@ -557,7 +564,8 @@ void *channel_init_try_register_connection_polling_without_gil(void *arg) { } // Needs to be called under global_connection_poolling_mu -void grpc_rb_channel_try_register_connection_polling(bg_watched_channel *bg) { +static void grpc_rb_channel_try_register_connection_polling( + bg_watched_channel *bg) { grpc_connectivity_state conn_state; watch_state_op *op = NULL; @@ -599,7 +607,7 @@ void grpc_rb_channel_try_register_connection_polling(bg_watched_channel *bg) { // indicates process shutdown. // In the worst case, this stops polling channel connectivity // early and falls back to current behavior. -void *run_poll_channels_loop_no_gil(void *arg) { +static void *run_poll_channels_loop_no_gil(void *arg) { grpc_event event; watch_state_op *op = NULL; bg_watched_channel *bg = NULL; @@ -643,7 +651,7 @@ void *run_poll_channels_loop_no_gil(void *arg) { } // Notify the channel polling loop to cleanup and shutdown. -void run_poll_channels_loop_unblocking_func(void *arg) { +static void run_poll_channels_loop_unblocking_func(void *arg) { bg_watched_channel *bg = NULL; (void)arg; @@ -677,7 +685,7 @@ void run_poll_channels_loop_unblocking_func(void *arg) { } // Poll channel connectivity states in background thread without the GIL. -VALUE run_poll_channels_loop(VALUE arg) { +static VALUE run_poll_channels_loop(VALUE arg) { (void)arg; gpr_log( GPR_DEBUG, @@ -688,7 +696,7 @@ VALUE run_poll_channels_loop(VALUE arg) { return Qnil; } -void *wait_until_channel_polling_thread_started_no_gil(void *arg) { +static void *wait_until_channel_polling_thread_started_no_gil(void *arg) { (void)arg; gpr_log(GPR_DEBUG, "GRPC_RUBY: wait for channel polling thread to start"); gpr_mu_lock(&global_connection_polling_mu); @@ -740,7 +748,7 @@ void grpc_rb_channel_polling_thread_start() { } } -void Init_grpc_propagate_masks() { +static void Init_grpc_propagate_masks() { /* Constants representing call propagation masks in grpc.h */ VALUE grpc_rb_mPropagateMasks = rb_define_module_under(grpc_rb_mGrpcCore, "PropagateMasks"); @@ -756,7 +764,7 @@ void Init_grpc_propagate_masks() { UINT2NUM(GRPC_PROPAGATE_DEFAULTS)); } -void Init_grpc_connectivity_states() { +static void Init_grpc_connectivity_states() { /* Constants representing call propagation masks in grpc.h */ VALUE grpc_rb_mConnectivityStates = rb_define_module_under(grpc_rb_mGrpcCore, "ConnectivityStates"); diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c index 9f3a81b1a8..fd75d2f691 100644 --- a/src/ruby/ext/grpc/rb_completion_queue.c +++ b/src/ruby/ext/grpc/rb_completion_queue.c @@ -71,16 +71,12 @@ static void *grpc_rb_completion_queue_pluck_no_gil(void *param) { } /* Helper function to free a completion queue. */ -void grpc_rb_completion_queue_safe_destroy(grpc_completion_queue *cq) { - grpc_event ev; - +void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq) { + /* Every function that adds an event to a queue also synchronously plucks + that event from the queue, and holds a reference to the Ruby object that + holds the queue, so we only get to this point if all of those functions + have completed, and the queue is empty */ grpc_completion_queue_shutdown(cq); - for(;;) { - ev = grpc_completion_queue_pluck(cq, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - if (ev.type == GRPC_QUEUE_SHUTDOWN) { - break; - } - } grpc_completion_queue_destroy(cq); } diff --git a/src/ruby/ext/grpc/rb_completion_queue.h b/src/ruby/ext/grpc/rb_completion_queue.h index eb041b28df..aa9dc6416a 100644 --- a/src/ruby/ext/grpc/rb_completion_queue.h +++ b/src/ruby/ext/grpc/rb_completion_queue.h @@ -38,7 +38,7 @@ #include -void grpc_rb_completion_queue_safe_destroy(grpc_completion_queue *cq); +void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq); /** * Makes the implementation of CompletionQueue#pluck available in other files diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c index 2a3b339102..e0be5d7f08 100644 --- a/src/ruby/ext/grpc/rb_grpc.c +++ b/src/ruby/ext/grpc/rb_grpc.c @@ -42,7 +42,6 @@ #include #include -#include #include "rb_call.h" #include "rb_call_credentials.h" #include "rb_channel.h" diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 2b0858c247..2286a99f24 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -77,7 +77,7 @@ static void destroy_server(grpc_rb_server *server, gpr_timespec deadline) { gpr_inf_future(GPR_CLOCK_REALTIME), NULL); } grpc_server_destroy(server->wrapped); - grpc_rb_completion_queue_safe_destroy(server->queue); + grpc_rb_completion_queue_destroy(server->queue); server->wrapped = NULL; server->queue = NULL; } diff --git a/src/ruby/spec/channel_connection_spec.rb b/src/ruby/spec/channel_connection_spec.rb index b3edec8f93..c8a7856a09 100644 --- a/src/ruby/spec/channel_connection_spec.rb +++ b/src/ruby/spec/channel_connection_spec.rb @@ -143,8 +143,7 @@ describe 'channel connection behavior' do stop_server end - it 'observably connects and reconnects to transient server' \ - ' when using the channel state API' do + it 'concurrent watches on the same channel' do timeout(180) do port = start_server ch = GRPC::Core::Channel.new("localhost:#{port}", {}, -- cgit v1.2.3 From c24d53b0cfffe2cd78d53c0c86de43346dcc7ee7 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 17 May 2017 20:25:38 -0700 Subject: api watch unblock func kills only its own channel --- .../multiple_killed_watching_threads_driver.rb | 56 ++++++++++++++++++++++ src/ruby/ext/grpc/rb_channel.c | 18 ++++--- .../helper_scripts/run_ruby_end2end_tests.sh | 1 + 3 files changed, 69 insertions(+), 6 deletions(-) create mode 100755 src/ruby/end2end/multiple_killed_watching_threads_driver.rb diff --git a/src/ruby/end2end/multiple_killed_watching_threads_driver.rb b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb new file mode 100755 index 0000000000..0c98915b7e --- /dev/null +++ b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb @@ -0,0 +1,56 @@ +#!/usr/bin/env ruby + +# 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_relative './end2end_common' + +Thread.abort_on_exception = true + +include GRPC::Core::ConnectivityStates + +def watch_state(ch) + thd = Thread.new do + state = ch.connectivity_state(false) + fail "non-idle state: #{state}" unless state == IDLE + ch.watch_connectivity_state(IDLE, Time.now + 360) + end + sleep 0.1 + thd.kill +end + +def main + 10.times do + ch = GRPC::Core::Channel.new('dummy_host', + nil, :this_channel_is_insecure) + watch_state(ch) + end +end + +main diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index e02dd0805d..6e7baa3122 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -366,6 +366,16 @@ static void *wait_for_watch_state_op_complete_without_gvl(void *arg) { return success; } +static void wait_for_watch_state_op_complete_unblocking_func(void *arg) { + bg_watched_channel *bg = (bg_watched_channel *)arg; + gpr_mu_lock(&global_connection_polling_mu); + if (!bg->channel_destroyed) { + grpc_channel_destroy(bg->channel); + bg->channel_destroyed = 1; + } + gpr_mu_unlock(&global_connection_polling_mu); +} + /* Wait until the channel's connectivity state becomes different from * "last_state", or "deadline" expires. * Returns true if the the channel's connectivity state becomes @@ -400,7 +410,7 @@ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, op_success = rb_thread_call_without_gvl( wait_for_watch_state_op_complete_without_gvl, &stack, - run_poll_channels_loop_unblocking_func, NULL); + wait_for_watch_state_op_complete_unblocking_func, wrapper->bg_wrapped); return op_success ? Qtrue : Qfalse; } @@ -577,11 +587,7 @@ static void grpc_rb_channel_try_register_connection_polling( return; } GPR_ASSERT(bg->refcount == 1); - if (bg->channel_destroyed) { - GPR_ASSERT(abort_channel_polling); - return; - } - if (abort_channel_polling) { + if (bg->channel_destroyed || abort_channel_polling) { return; } diff --git a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh index 6688025260..ab882d62bc 100755 --- a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh +++ b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh @@ -41,4 +41,5 @@ ruby src/ruby/end2end/sig_int_during_channel_watch_driver.rb || EXIT_CODE=1 ruby src/ruby/end2end/killed_client_thread_driver.rb || EXIT_CODE=1 ruby src/ruby/end2end/forking_client_driver.rb || EXIT_CODE=1 ruby src/ruby/end2end/grpc_class_init_driver.rb || EXIT_CODE=1 +ruby src/ruby/end2end/multiple_killed_watching_threads_driver.rb || EXIT_CODE=1 exit $EXIT_CODE -- cgit v1.2.3 From d7455abfbd1394a6984b901a305785e9cba7b2d6 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 17 May 2017 21:39:09 -0700 Subject: make get conn state always safe to call --- src/ruby/end2end/multiple_killed_watching_threads_driver.rb | 7 +++++++ src/ruby/ext/grpc/rb_channel.c | 12 ++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/ruby/end2end/multiple_killed_watching_threads_driver.rb b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb index 0c98915b7e..206ec8e801 100755 --- a/src/ruby/end2end/multiple_killed_watching_threads_driver.rb +++ b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb @@ -46,10 +46,17 @@ def watch_state(ch) end def main + channels = [] 10.times do ch = GRPC::Core::Channel.new('dummy_host', nil, :this_channel_is_insecure) watch_state(ch) + channels << ch + end + + # checking state should still be safe to call + channels.each do |c| + fail unless c.connectivity_state(false) == FATAL_FAILURE end end diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 6e7baa3122..0524c49710 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -273,7 +273,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { } typedef struct get_state_stack { - grpc_channel *channel; + bg_watched_channel *bg; int try_to_connect; int out; } get_state_stack; @@ -283,14 +283,10 @@ static void *get_state_without_gil(void *arg) { gpr_mu_lock(&global_connection_polling_mu); GPR_ASSERT(abort_channel_polling || channel_polling_thread_started); - if (abort_channel_polling) { - // Assume that this channel has been destroyed by the - // background thread. - // The case in which the channel polling thread - // failed to start just always shows shutdown state. + if (stack->bg->channel_destroyed) { stack->out = GRPC_CHANNEL_SHUTDOWN; } else { - stack->out = grpc_channel_check_connectivity_state(stack->channel, + stack->out = grpc_channel_check_connectivity_state(stack->bg->channel, stack->try_to_connect); } gpr_mu_unlock(&global_connection_polling_mu); @@ -322,7 +318,7 @@ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, return Qnil; } - stack.channel = wrapper->bg_wrapped->channel; + stack.bg = wrapper->bg_wrapped; stack.try_to_connect = RTEST(try_to_connect_param) ? 1 : 0; rb_thread_call_without_gvl(get_state_without_gil, &stack, NULL, NULL); -- cgit v1.2.3 From 82fef0bce75fd18fb468ad8a9363040e6c6e84fc Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 17 May 2017 23:42:38 -0700 Subject: tentative fix for global side effect on interrupted constructor --- src/ruby/ext/grpc/rb_channel.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 0524c49710..7aaa71eeaf 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -107,6 +107,7 @@ static bg_watched_channel *bg_watched_channel_list_head = NULL; static void grpc_rb_channel_try_register_connection_polling( bg_watched_channel *bg); static void *wait_until_channel_polling_thread_started_no_gil(void *); +static void wait_until_channel_polling_thread_started_unblocking_func(void *); static void *channel_init_try_register_connection_polling_without_gil( void *arg); @@ -227,12 +228,15 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { char *target_chars = NULL; grpc_channel_args args; channel_init_try_register_stack stack; + int stop_waiting_for_thread_start = 0; MEMZERO(&args, grpc_channel_args, 1); grpc_ruby_once_init(); - rb_thread_call_without_gvl(wait_until_channel_polling_thread_started_no_gil, - NULL, run_poll_channels_loop_unblocking_func, - NULL); + rb_thread_call_without_gvl( + wait_until_channel_polling_thread_started_no_gil, + &stop_waiting_for_thread_start, + wait_until_channel_polling_thread_started_unblocking_func, + &stop_waiting_for_thread_start); /* "3" == 3 mandatory args */ rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials); @@ -699,10 +703,11 @@ static VALUE run_poll_channels_loop(VALUE arg) { } static void *wait_until_channel_polling_thread_started_no_gil(void *arg) { - (void)arg; + int *stop_waiting = (int *)arg; gpr_log(GPR_DEBUG, "GRPC_RUBY: wait for channel polling thread to start"); gpr_mu_lock(&global_connection_polling_mu); - while (!channel_polling_thread_started && !abort_channel_polling) { + while (!channel_polling_thread_started && !abort_channel_polling && + !*stop_waiting) { gpr_cv_wait(&global_connection_polling_cv, &global_connection_polling_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } @@ -711,6 +716,17 @@ static void *wait_until_channel_polling_thread_started_no_gil(void *arg) { return NULL; } +static void wait_until_channel_polling_thread_started_unblocking_func( + void *arg) { + int *stop_waiting = (int *)arg; + gpr_mu_lock(&global_connection_polling_mu); + gpr_log(GPR_DEBUG, + "GRPC_RUBY: interrupt wait for channel polling thread to start"); + *stop_waiting = 1; + gpr_cv_broadcast(&global_connection_polling_cv); + gpr_mu_unlock(&global_connection_polling_mu); +} + static void *set_abort_channel_polling_without_gil(void *arg) { (void)arg; gpr_mu_lock(&global_connection_polling_mu); -- cgit v1.2.3 From 92eb7fbc05903def20434c110193481913c2e38a Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 18 May 2017 11:49:15 -0700 Subject: Bump to version 1.3.4 --- BUILD | 2 +- CMakeLists.txt | 2 +- Makefile | 4 ++-- build.yaml | 2 +- gRPC-Core.podspec | 2 +- gRPC-ProtoRPC.podspec | 2 +- gRPC-RxLibrary.podspec | 2 +- gRPC.podspec | 2 +- package.json | 2 +- package.xml | 4 ++-- src/cpp/common/version_cc.cc | 2 +- src/csharp/Grpc.Core/Version.csproj.include | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 4 ++-- src/csharp/build_packages_dotnetcli.bat | 2 +- src/csharp/build_packages_dotnetcli.sh | 4 ++-- src/node/health_check/package.json | 4 ++-- src/node/tools/package.json | 2 +- src/objective-c/!ProtoCompiler-gRPCPlugin.podspec | 2 +- src/objective-c/GRPCClient/private/version.h | 2 +- src/php/composer.json | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/python/grpcio_health_checking/grpc_version.py | 2 +- src/python/grpcio_reflection/grpc_version.py | 2 +- src/python/grpcio_tests/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- 29 files changed, 34 insertions(+), 34 deletions(-) diff --git a/BUILD b/BUILD index a0d80cd573..51314f645c 100644 --- a/BUILD +++ b/BUILD @@ -42,7 +42,7 @@ g_stands_for = "gentle" core_version = "3.0.0" -version = "1.3.3" +version = "1.3.4" grpc_cc_library( name = "gpr", diff --git a/CMakeLists.txt b/CMakeLists.txt index 279e12bbd0..e344e413d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.3.3") +set(PACKAGE_VERSION "1.3.4") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") diff --git a/Makefile b/Makefile index e5f23e75ad..88bb5b5e5f 100644 --- a/Makefile +++ b/Makefile @@ -420,8 +420,8 @@ Q = @ endif CORE_VERSION = 3.0.0 -CPP_VERSION = 1.3.3 -CSHARP_VERSION = 1.3.3 +CPP_VERSION = 1.3.4 +CSHARP_VERSION = 1.3.4 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/build.yaml b/build.yaml index 5d1e74b93a..a42c9cf550 100644 --- a/build.yaml +++ b/build.yaml @@ -14,7 +14,7 @@ settings: '#10': See the expand_version.py for all the quirks here core_version: 3.0.0 g_stands_for: gentle - version: 1.3.3 + version: 1.3.4 filegroups: - name: census public_headers: diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index a2237ac085..c8e50b577a 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -37,7 +37,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.3.3' + version = '1.3.4' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'http://www.grpc.io' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 1af811aa55..6737e0136a 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.3.3' + version = '1.3.4' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'http://www.grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 3f720f2393..0b338d44aa 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.3.3' + version = '1.3.4' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'http://www.grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index b064c50ccf..1783df67ef 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -35,7 +35,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.3.3' + version = '1.3.4' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'http://www.grpc.io' diff --git a/package.json b/package.json index 2cb86a65a3..11e3441652 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "1.3.3", + "version": "1.3.4", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", diff --git a/package.xml b/package.xml index faf3665757..6b3eddadf6 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2017-05-05 - 1.3.3 - 1.3.3 + 1.3.4 + 1.3.4 beta diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index 2d44fb9d08..97437ba530 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -37,5 +37,5 @@ #include namespace grpc { -grpc::string Version() { return "1.3.3"; } +grpc::string Version() { return "1.3.4"; } } diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 9ececc9b95..881c311b17 100755 --- a/src/csharp/Grpc.Core/Version.csproj.include +++ b/src/csharp/Grpc.Core/Version.csproj.include @@ -1,7 +1,7 @@ - 1.3.3 + 1.3.4 3.2.0 diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index 12cbc6f049..bbe5a17d6b 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -48,11 +48,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "1.3.3.0"; + public const string CurrentAssemblyFileVersion = "1.3.4.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "1.3.3"; + public const string CurrentVersion = "1.3.4"; } } diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index 6806bbd2ae..a385ac74e3 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -28,7 +28,7 @@ @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem Current package versions -set VERSION=1.3.3 +set VERSION=1.3.4 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh index fc9fd50f59..66c41d4d94 100755 --- a/src/csharp/build_packages_dotnetcli.sh +++ b/src/csharp/build_packages_dotnetcli.sh @@ -70,7 +70,7 @@ dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts -nuget pack Grpc.nuspec -Version "1.3.3" -OutputDirectory ../../artifacts -nuget pack Grpc.Tools.nuspec -Version "1.3.3" -OutputDirectory ../../artifacts +nuget pack Grpc.nuspec -Version "1.3.4" -OutputDirectory ../../artifacts +nuget pack Grpc.Tools.nuspec -Version "1.3.4" -OutputDirectory ../../artifacts (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg) diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json index fe36fb2693..6329cd9c37 100644 --- a/src/node/health_check/package.json +++ b/src/node/health_check/package.json @@ -1,6 +1,6 @@ { "name": "grpc-health-check", - "version": "1.3.3", + "version": "1.3.4", "author": "Google Inc.", "description": "Health check service for use with gRPC", "repository": { @@ -15,7 +15,7 @@ } ], "dependencies": { - "grpc": "^1.3.3", + "grpc": "^1.3.4", "lodash": "^3.9.3", "google-protobuf": "^3.0.0" }, diff --git a/src/node/tools/package.json b/src/node/tools/package.json index caf2b5a5cb..355ae2fdc1 100644 --- a/src/node/tools/package.json +++ b/src/node/tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "1.3.3", + "version": "1.3.4", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "http://www.grpc.io/", diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 4e93c0f1b5..b4fc968504 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.3.3' + v = '1.3.4' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index 66408f5bbb..ccf96230bc 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -38,4 +38,4 @@ // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.3.3" +#define GRPC_OBJC_VERSION_STRING @"1.3.4" diff --git a/src/php/composer.json b/src/php/composer.json index bbe33974d5..562859e6b3 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "BSD-3-Clause", - "version": "1.3.3", + "version": "1.3.4", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.1.0" diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 027f6caf28..29ffcab106 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION='1.3.3' +VERSION='1.3.4' diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index f2db8bb056..16e0dc1327 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION='1.3.3' +VERSION='1.3.4' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index 3f33eb3ed5..5ef0ed8045 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION='1.3.3' +VERSION='1.3.4' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index 1a681d0136..7e4c57e6ec 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION='1.3.3' +VERSION='1.3.4' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 4ab94c9132..c03ec97196 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.3.3' + VERSION = '1.3.4' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 58e05d0814..fe0fb2cef2 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -29,6 +29,6 @@ module GRPC module Tools - VERSION = '1.3.3' + VERSION = '1.3.4' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index ecfa9d85e3..020785aa73 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION='1.3.3' +VERSION='1.3.4' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 8067aa764c..5021a1a153 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.3.3 +PROJECT_NUMBER = 1.3.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 1a94b01e35..1df6951aef 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.3.3 +PROJECT_NUMBER = 1.3.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a -- cgit v1.2.3 From c3b1f18a7e7f443329f95ff25485c503ab76cc69 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Tue, 18 Apr 2017 13:51:36 -0700 Subject: get rid of connectivity state watchers right after timeout --- CMakeLists.txt | 32 +++ Makefile | 36 ++++ build.yaml | 12 ++ grpc.def | 1 + include/grpc/grpc.h | 6 + .../filters/client_channel/channel_connectivity.c | 77 ++++--- .../ext/filters/client_channel/client_channel.c | 115 ++++++++++- .../ext/filters/client_channel/client_channel.h | 6 +- src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 + src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 + test/core/surface/concurrent_connectivity_test.c | 69 ++++++- .../num_external_connectivity_watchers_test.c | 221 +++++++++++++++++++++ test/core/surface/sequential_connectivity_test.c | 3 + tools/run_tests/generated/sources_and_headers.json | 17 ++ tools/run_tests/generated/tests.json | 24 +++ vsprojects/buildtests_c.sln | 27 +++ ...num_external_connectivity_watchers_test.vcxproj | 199 +++++++++++++++++++ ...rnal_connectivity_watchers_test.vcxproj.filters | 21 ++ 18 files changed, 837 insertions(+), 34 deletions(-) create mode 100644 test/core/surface/num_external_connectivity_watchers_test.c create mode 100644 vsprojects/vcxproj/test/num_external_connectivity_watchers_test/num_external_connectivity_watchers_test.vcxproj create mode 100644 vsprojects/vcxproj/test/num_external_connectivity_watchers_test/num_external_connectivity_watchers_test.vcxproj.filters diff --git a/CMakeLists.txt b/CMakeLists.txt index 81dba56b9e..553caab880 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -475,6 +475,7 @@ add_dependencies(buildtests_c mlog_test) add_dependencies(buildtests_c multiple_server_queues_test) add_dependencies(buildtests_c murmur_hash_test) add_dependencies(buildtests_c no_server_test) +add_dependencies(buildtests_c num_external_connectivity_watchers_test) add_dependencies(buildtests_c parse_address_test) add_dependencies(buildtests_c percent_encoding_test) if(_gRPC_PLATFORM_LINUX) @@ -7580,6 +7581,37 @@ target_link_libraries(no_server_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(num_external_connectivity_watchers_test + test/core/surface/num_external_connectivity_watchers_test.c +) + + +target_include_directories(num_external_connectivity_watchers_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_BUILD_INCLUDE_DIR} + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CARES_PLATFORM_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include +) + +target_link_libraries(num_external_connectivity_watchers_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(parse_address_test test/core/client_channel/parse_address_test.c ) diff --git a/Makefile b/Makefile index 9e3daabe40..68dc9de492 100644 --- a/Makefile +++ b/Makefile @@ -1056,6 +1056,7 @@ murmur_hash_test: $(BINDIR)/$(CONFIG)/murmur_hash_test nanopb_fuzzer_response_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test no_server_test: $(BINDIR)/$(CONFIG)/no_server_test +num_external_connectivity_watchers_test: $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test parse_address_test: $(BINDIR)/$(CONFIG)/parse_address_test percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer @@ -1427,6 +1428,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/multiple_server_queues_test \ $(BINDIR)/$(CONFIG)/murmur_hash_test \ $(BINDIR)/$(CONFIG)/no_server_test \ + $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test \ $(BINDIR)/$(CONFIG)/parse_address_test \ $(BINDIR)/$(CONFIG)/percent_encoding_test \ $(BINDIR)/$(CONFIG)/pollset_set_test \ @@ -1883,6 +1885,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/murmur_hash_test || ( echo test murmur_hash_test failed ; exit 1 ) $(E) "[RUN] Testing no_server_test" $(Q) $(BINDIR)/$(CONFIG)/no_server_test || ( echo test no_server_test failed ; exit 1 ) + $(E) "[RUN] Testing num_external_connectivity_watchers_test" + $(Q) $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test || ( echo test num_external_connectivity_watchers_test failed ; exit 1 ) $(E) "[RUN] Testing parse_address_test" $(Q) $(BINDIR)/$(CONFIG)/parse_address_test || ( echo test parse_address_test failed ; exit 1 ) $(E) "[RUN] Testing percent_encoding_test" @@ -11810,6 +11814,38 @@ endif endif +NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC = \ + test/core/surface/num_external_connectivity_watchers_test.c \ + +NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test: $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/surface/num_external_connectivity_watchers_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_num_external_connectivity_watchers_test: $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS:.o=.dep) +endif +endif + + PARSE_ADDRESS_TEST_SRC = \ test/core/client_channel/parse_address_test.c \ diff --git a/build.yaml b/build.yaml index 5f23562022..cb9e67ff0b 100644 --- a/build.yaml +++ b/build.yaml @@ -2586,6 +2586,18 @@ targets: - grpc - gpr_test_util - gpr +- name: num_external_connectivity_watchers_test + build: test + language: c + src: + - test/core/surface/num_external_connectivity_watchers_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + exclude_iomgrs: + - uv - name: parse_address_test build: test language: c diff --git a/grpc.def b/grpc.def index 1589316a58..534a23d600 100644 --- a/grpc.def +++ b/grpc.def @@ -65,6 +65,7 @@ EXPORTS grpc_alarm_cancel grpc_alarm_destroy grpc_channel_check_connectivity_state + grpc_channel_num_external_connectivity_watchers grpc_channel_watch_connectivity_state grpc_channel_create_call grpc_channel_ping diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index e088435d6c..bdb8617411 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -225,6 +225,12 @@ GRPCAPI void grpc_alarm_destroy(grpc_alarm *alarm); GRPCAPI grpc_connectivity_state grpc_channel_check_connectivity_state( grpc_channel *channel, int try_to_connect); +/** Number of active "external connectivity state watchers" attached to a + * channel. + * Useful for testing. **/ +GRPCAPI int grpc_channel_num_external_connectivity_watchers( + grpc_channel *channel); + /** Watch for a change in connectivity state. Once the channel connectivity state is different from last_observed_state, tag will be enqueued on cq with success=1. diff --git a/src/core/ext/filters/client_channel/channel_connectivity.c b/src/core/ext/filters/client_channel/channel_connectivity.c index 62f58fb278..5f3ffd4947 100644 --- a/src/core/ext/filters/client_channel/channel_connectivity.c +++ b/src/core/ext/filters/client_channel/channel_connectivity.c @@ -67,9 +67,8 @@ grpc_connectivity_state grpc_channel_check_connectivity_state( typedef enum { WAITING, - CALLING_BACK, + READY_TO_CALL_BACK, CALLING_BACK_AND_FINISHED, - CALLED_BACK } callback_phase; typedef struct { @@ -77,11 +76,13 @@ typedef struct { callback_phase phase; grpc_closure on_complete; grpc_closure on_timeout; + grpc_closure watcher_timer_init; grpc_timer alarm; grpc_connectivity_state state; grpc_completion_queue *cq; grpc_cq_completion completion_storage; grpc_channel *channel; + grpc_error *error; void *tag; } state_watcher; @@ -105,11 +106,8 @@ static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw, gpr_mu_lock(&w->mu); switch (w->phase) { case WAITING: - case CALLED_BACK: + case READY_TO_CALL_BACK: GPR_UNREACHABLE_CODE(return ); - case CALLING_BACK: - w->phase = CALLED_BACK; - break; case CALLING_BACK_AND_FINISHED: delete = 1; break; @@ -123,10 +121,14 @@ static void finished_completion(grpc_exec_ctx *exec_ctx, void *pw, static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w, bool due_to_completion, grpc_error *error) { - int delete = 0; - if (due_to_completion) { grpc_timer_cancel(exec_ctx, &w->alarm); + } else { + grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element( + grpc_channel_get_channel_stack(w->channel)); + grpc_client_channel_watch_connectivity_state(exec_ctx, client_channel_elem, + grpc_cq_pollset(w->cq), NULL, + &w->on_complete, NULL); } gpr_mu_lock(&w->mu); @@ -147,25 +149,27 @@ static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w, } switch (w->phase) { case WAITING: - w->phase = CALLING_BACK; - grpc_cq_end_op(exec_ctx, w->cq, w->tag, GRPC_ERROR_REF(error), - finished_completion, w, &w->completion_storage); + GRPC_ERROR_REF(error); + w->error = error; + w->phase = READY_TO_CALL_BACK; break; - case CALLING_BACK: + case READY_TO_CALL_BACK: + if (error != GRPC_ERROR_NONE) { + GPR_ASSERT(!due_to_completion); + GRPC_ERROR_UNREF(w->error); + GRPC_ERROR_REF(error); + w->error = error; + } w->phase = CALLING_BACK_AND_FINISHED; + grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->error, finished_completion, w, + &w->completion_storage); break; case CALLING_BACK_AND_FINISHED: GPR_UNREACHABLE_CODE(return ); - case CALLED_BACK: - delete = 1; break; } gpr_mu_unlock(&w->mu); - if (delete) { - delete_state_watcher(exec_ctx, w); - } - GRPC_ERROR_UNREF(error); } @@ -179,6 +183,28 @@ static void timeout_complete(grpc_exec_ctx *exec_ctx, void *pw, partly_done(exec_ctx, pw, false, GRPC_ERROR_REF(error)); } +int grpc_channel_num_external_connectivity_watchers(grpc_channel *channel) { + grpc_channel_element *client_channel_elem = + grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); + return grpc_client_channel_num_external_connectivity_watchers( + client_channel_elem); +} + +typedef struct watcher_timer_init_arg { + state_watcher *w; + gpr_timespec deadline; +} watcher_timer_init_arg; + +static void watcher_timer_init(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error_ignored) { + watcher_timer_init_arg *wa = (watcher_timer_init_arg *)arg; + + grpc_timer_init(exec_ctx, &wa->w->alarm, + gpr_convert_clock_type(wa->deadline, GPR_CLOCK_MONOTONIC), + &wa->w->on_timeout, gpr_now(GPR_CLOCK_MONOTONIC)); + gpr_free(wa); +} + void grpc_channel_watch_connectivity_state( grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag) { @@ -208,16 +234,19 @@ void grpc_channel_watch_connectivity_state( w->cq = cq; w->tag = tag; w->channel = channel; + w->error = NULL; - grpc_timer_init(&exec_ctx, &w->alarm, - gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), - &w->on_timeout, gpr_now(GPR_CLOCK_MONOTONIC)); + watcher_timer_init_arg *wa = gpr_malloc(sizeof(watcher_timer_init_arg)); + wa->w = w; + wa->deadline = deadline; + grpc_closure_init(&w->watcher_timer_init, watcher_timer_init, wa, + grpc_schedule_on_exec_ctx); if (client_channel_elem->filter == &grpc_client_channel_filter) { GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity"); - grpc_client_channel_watch_connectivity_state(&exec_ctx, client_channel_elem, - grpc_cq_pollset(cq), &w->state, - &w->on_complete); + grpc_client_channel_watch_connectivity_state( + &exec_ctx, client_channel_elem, grpc_cq_pollset(cq), &w->state, + &w->on_complete, &w->watcher_timer_init); } else { abort(); } diff --git a/src/core/ext/filters/client_channel/client_channel.c b/src/core/ext/filters/client_channel/client_channel.c index 83e3b8f118..4bd153e8ac 100644 --- a/src/core/ext/filters/client_channel/client_channel.c +++ b/src/core/ext/filters/client_channel/client_channel.c @@ -174,6 +174,8 @@ static void *method_parameters_create_from_json(const grpc_json *json) { return value; } +struct external_connectivity_watcher; + /************************************************************************* * CHANNEL-WIDE FUNCTIONS */ @@ -209,6 +211,11 @@ typedef struct client_channel_channel_data { /** interested parties (owned) */ grpc_pollset_set *interested_parties; + /* external_connectivity_watcher_list head is guarded by its own mutex, since + * counts need to be grabbed immediately without polling on a cq */ + gpr_mu external_connectivity_watcher_list_mu; + struct external_connectivity_watcher *external_connectivity_watcher_list_head; + /* the following properties are guarded by a mutex since API's require them to be instantaneously available */ gpr_mu info_mu; @@ -632,6 +639,12 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx, // Initialize data members. chand->combiner = grpc_combiner_create(NULL); gpr_mu_init(&chand->info_mu); + gpr_mu_init(&chand->external_connectivity_watcher_list_mu); + + gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); + chand->external_connectivity_watcher_list_head = NULL; + gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); + chand->owning_stack = args->channel_stack; grpc_closure_init(&chand->on_resolver_result_changed, on_resolver_result_changed_locked, chand, @@ -718,6 +731,7 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_pollset_set_destroy(exec_ctx, chand->interested_parties); GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel"); gpr_mu_destroy(&chand->info_mu); + gpr_mu_destroy(&chand->external_connectivity_watcher_list_mu); } /************************************************************************* @@ -1361,14 +1375,79 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state( return out; } -typedef struct { +typedef struct external_connectivity_watcher { channel_data *chand; grpc_pollset *pollset; grpc_closure *on_complete; + grpc_closure *watcher_timer_init; grpc_connectivity_state *state; grpc_closure my_closure; + struct external_connectivity_watcher *next; } external_connectivity_watcher; +static external_connectivity_watcher *lookup_external_connectivity_watcher( + channel_data *chand, grpc_closure *on_complete) { + gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); + external_connectivity_watcher *w = + chand->external_connectivity_watcher_list_head; + while (w != NULL && w->on_complete != on_complete) { + w = w->next; + } + gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); + return w; +} + +static void external_connectivity_watcher_list_append( + channel_data *chand, external_connectivity_watcher *w) { + GPR_ASSERT(!lookup_external_connectivity_watcher(chand, w->on_complete)); + + gpr_mu_lock(&w->chand->external_connectivity_watcher_list_mu); + GPR_ASSERT(!w->next); + w->next = chand->external_connectivity_watcher_list_head; + chand->external_connectivity_watcher_list_head = w; + gpr_mu_unlock(&w->chand->external_connectivity_watcher_list_mu); +} + +static void external_connectivity_watcher_list_remove( + channel_data *chand, external_connectivity_watcher *too_remove) { + GPR_ASSERT( + lookup_external_connectivity_watcher(chand, too_remove->on_complete)); + gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); + if (too_remove == chand->external_connectivity_watcher_list_head) { + chand->external_connectivity_watcher_list_head = too_remove->next; + gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); + return; + } + external_connectivity_watcher *w = + chand->external_connectivity_watcher_list_head; + while (w != NULL) { + if (w->next == too_remove) { + w->next = w->next->next; + gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); + return; + } + w = w->next; + } + GPR_UNREACHABLE_CODE(return ); +} + +int grpc_client_channel_num_external_connectivity_watchers( + grpc_channel_element *elem) { + channel_data *chand = elem->channel_data; + int count = 0; + + gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); + external_connectivity_watcher *w = + chand->external_connectivity_watcher_list_head; + while (w != NULL) { + count++; + w = w->next; + } + gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); + + return count; +} + static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { external_connectivity_watcher *w = arg; @@ -1377,6 +1456,7 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg, w->pollset); GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "external_connectivity_watcher"); + external_connectivity_watcher_list_remove(w->chand, w); gpr_free(w); grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error)); } @@ -1384,21 +1464,42 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg, static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error_ignored) { external_connectivity_watcher *w = arg; - grpc_closure_init(&w->my_closure, on_external_watch_complete, w, - grpc_schedule_on_exec_ctx); - grpc_connectivity_state_notify_on_state_change( - exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure); + external_connectivity_watcher *found = NULL; + if (w->state != NULL) { + external_connectivity_watcher_list_append(w->chand, w); + grpc_closure_run(exec_ctx, w->watcher_timer_init, GRPC_ERROR_NONE); + grpc_closure_init(&w->my_closure, on_external_watch_complete, w, + grpc_schedule_on_exec_ctx); + grpc_connectivity_state_notify_on_state_change( + exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure); + } else { + GPR_ASSERT(w->watcher_timer_init == NULL); + found = lookup_external_connectivity_watcher(w->chand, w->on_complete); + if (found) { + GPR_ASSERT(found->on_complete == w->on_complete); + grpc_connectivity_state_notify_on_state_change( + exec_ctx, &found->chand->state_tracker, NULL, &found->my_closure); + } + grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties, + w->pollset); + GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, + "external_connectivity_watcher"); + gpr_free(w); + } } void grpc_client_channel_watch_connectivity_state( grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset, - grpc_connectivity_state *state, grpc_closure *on_complete) { + grpc_connectivity_state *state, grpc_closure *on_complete, + grpc_closure *watcher_timer_init) { channel_data *chand = elem->channel_data; - external_connectivity_watcher *w = gpr_malloc(sizeof(*w)); + external_connectivity_watcher *w = gpr_zalloc(sizeof(*w)); w->chand = chand; w->pollset = pollset; w->on_complete = on_complete; w->state = state; + w->watcher_timer_init = watcher_timer_init; + grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset); GRPC_CHANNEL_STACK_REF(w->chand->owning_stack, "external_connectivity_watcher"); diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h index 8d2490ea55..356a7ab0c1 100644 --- a/src/core/ext/filters/client_channel/client_channel.h +++ b/src/core/ext/filters/client_channel/client_channel.h @@ -53,9 +53,13 @@ extern const grpc_channel_filter grpc_client_channel_filter; grpc_connectivity_state grpc_client_channel_check_connectivity_state( grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect); +int grpc_client_channel_num_external_connectivity_watchers( + grpc_channel_element *elem); + void grpc_client_channel_watch_connectivity_state( grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset, - grpc_connectivity_state *state, grpc_closure *on_complete); + grpc_connectivity_state *state, grpc_closure *on_complete, + grpc_closure *watcher_timer_init); /* Debug helper: pull the subchannel call from a call stack element */ grpc_subchannel_call *grpc_client_channel_get_subchannel_call( diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 063f92114c..332907c0af 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -103,6 +103,7 @@ grpc_alarm_create_type grpc_alarm_create_import; grpc_alarm_cancel_type grpc_alarm_cancel_import; grpc_alarm_destroy_type grpc_alarm_destroy_import; grpc_channel_check_connectivity_state_type grpc_channel_check_connectivity_state_import; +grpc_channel_num_external_connectivity_watchers_type grpc_channel_num_external_connectivity_watchers_import; grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import; grpc_channel_create_call_type grpc_channel_create_call_import; grpc_channel_ping_type grpc_channel_ping_import; @@ -400,6 +401,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_alarm_cancel_import = (grpc_alarm_cancel_type) GetProcAddress(library, "grpc_alarm_cancel"); grpc_alarm_destroy_import = (grpc_alarm_destroy_type) GetProcAddress(library, "grpc_alarm_destroy"); grpc_channel_check_connectivity_state_import = (grpc_channel_check_connectivity_state_type) GetProcAddress(library, "grpc_channel_check_connectivity_state"); + grpc_channel_num_external_connectivity_watchers_import = (grpc_channel_num_external_connectivity_watchers_type) GetProcAddress(library, "grpc_channel_num_external_connectivity_watchers"); grpc_channel_watch_connectivity_state_import = (grpc_channel_watch_connectivity_state_type) GetProcAddress(library, "grpc_channel_watch_connectivity_state"); grpc_channel_create_call_import = (grpc_channel_create_call_type) GetProcAddress(library, "grpc_channel_create_call"); grpc_channel_ping_import = (grpc_channel_ping_type) GetProcAddress(library, "grpc_channel_ping"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index f5dcd68a8e..e6a3f6d2f4 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -260,6 +260,9 @@ extern grpc_alarm_destroy_type grpc_alarm_destroy_import; typedef grpc_connectivity_state(*grpc_channel_check_connectivity_state_type)(grpc_channel *channel, int try_to_connect); extern grpc_channel_check_connectivity_state_type grpc_channel_check_connectivity_state_import; #define grpc_channel_check_connectivity_state grpc_channel_check_connectivity_state_import +typedef int(*grpc_channel_num_external_connectivity_watchers_type)(grpc_channel *channel); +extern grpc_channel_num_external_connectivity_watchers_type grpc_channel_num_external_connectivity_watchers_import; +#define grpc_channel_num_external_connectivity_watchers grpc_channel_num_external_connectivity_watchers_import typedef void(*grpc_channel_watch_connectivity_state_type)(grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag); extern grpc_channel_watch_connectivity_state_type grpc_channel_watch_connectivity_state_import; #define grpc_channel_watch_connectivity_state grpc_channel_watch_connectivity_state_import diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c index 2f7c3dfb85..73f2cd363e 100644 --- a/test/core/surface/concurrent_connectivity_test.c +++ b/test/core/surface/concurrent_connectivity_test.c @@ -61,6 +61,14 @@ #define DELAY_MILLIS 10 #define POLL_MILLIS 3000 +#define NUM_OUTER_LOOPS_SHORT_TIMEOUTS 10 +#define NUM_INNER_LOOPS_SHORT_TIMEOUTS 100 +#define DELAY_MILLIS_SHORT_TIMEOUTS 1 +// in a successful test run, POLL_MILLIS should never be reached beause all runs +// should +// end after the shorter delay_millis +#define POLL_MILLIS_SHORT_TIMEOUTS 30000 + static void *tag(int n) { return (void *)(uintptr_t)n; } static int detag(void *p) { return (int)(uintptr_t)p; } @@ -79,6 +87,8 @@ void create_loop_destroy(void *addr) { grpc_timeout_milliseconds_to_deadline(POLL_MILLIS); GPR_ASSERT(grpc_completion_queue_next(cq, poll_time, NULL).type == GRPC_OP_COMPLETE); + /* check that the watcher from "watch state" was free'd */ + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(chan) == 0); } grpc_channel_destroy(chan); grpc_completion_queue_destroy(cq); @@ -166,11 +176,10 @@ static void done_pollset_shutdown(grpc_exec_ctx *exec_ctx, void *pollset, gpr_free(pollset); } -int main(int argc, char **argv) { +int run_concurrent_connectivity_test() { struct server_thread_args args; memset(&args, 0, sizeof(args)); - grpc_test_init(argc, argv); grpc_init(); gpr_thd_id threads[NUM_THREADS]; @@ -240,3 +249,59 @@ int main(int argc, char **argv) { grpc_shutdown(); return 0; } + +void watches_with_short_timeouts(void *addr) { + for (int i = 0; i < NUM_OUTER_LOOPS_SHORT_TIMEOUTS; ++i) { + grpc_completion_queue *cq = grpc_completion_queue_create(NULL); + grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL); + + for (int j = 0; j < NUM_INNER_LOOPS_SHORT_TIMEOUTS; ++j) { + gpr_timespec later_time = + grpc_timeout_milliseconds_to_deadline(DELAY_MILLIS_SHORT_TIMEOUTS); + grpc_connectivity_state state = + grpc_channel_check_connectivity_state(chan, 0); + GPR_ASSERT(state == GRPC_CHANNEL_IDLE); + grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL); + gpr_timespec poll_time = + grpc_timeout_milliseconds_to_deadline(POLL_MILLIS_SHORT_TIMEOUTS); + grpc_event ev = grpc_completion_queue_next(cq, poll_time, NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.success == false); + /* check that the watcher from "watch state" was free'd */ + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(chan) == 0); + } + grpc_channel_destroy(chan); + grpc_completion_queue_destroy(cq); + } +} + +// This test tries to catch deadlock situations. +// With short timeouts on "watches" and long timeouts on cq next calls, +// so that a QUEUE_TIMEOUT likely means that something is stuck. +int run_concurrent_watches_with_short_timeouts_test() { + grpc_init(); + + gpr_thd_id threads[NUM_THREADS]; + + char *localhost = gpr_strdup("localhost:54321"); + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_new(&threads[i], watches_with_short_timeouts, localhost, &options); + } + for (size_t i = 0; i < NUM_THREADS; ++i) { + gpr_thd_join(threads[i]); + } + gpr_free(localhost); + + grpc_shutdown(); + return 0; +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + run_concurrent_connectivity_test(); + run_concurrent_watches_with_short_timeouts_test(); +} diff --git a/test/core/surface/num_external_connectivity_watchers_test.c b/test/core/surface/num_external_connectivity_watchers_test.c new file mode 100644 index 0000000000..96288ab60d --- /dev/null +++ b/test/core/surface/num_external_connectivity_watchers_test.c @@ -0,0 +1,221 @@ +/* + * + * 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 +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +typedef struct test_fixture { + const char *name; + grpc_channel *(*create_channel)(const char *addr); +} test_fixture; + +static size_t next_tag = 1; + +static void channel_idle_start_watch(grpc_channel *channel, + grpc_completion_queue *cq) { + gpr_timespec connect_deadline = grpc_timeout_milliseconds_to_deadline(1); + GPR_ASSERT(grpc_channel_check_connectivity_state(channel, 0) == + GRPC_CHANNEL_IDLE); + + grpc_channel_watch_connectivity_state( + channel, GRPC_CHANNEL_IDLE, connect_deadline, cq, (void *)(next_tag++)); + gpr_log(GPR_DEBUG, "number of active connect watchers: %d", + grpc_channel_num_external_connectivity_watchers(channel)); +} + +static void channel_idle_poll_for_timeout(grpc_channel *channel, + grpc_completion_queue *cq) { + grpc_event ev = + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + /* expect watch_connectivity_state to end with a timeout */ + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + GPR_ASSERT(ev.success == false); + GPR_ASSERT(grpc_channel_check_connectivity_state(channel, 0) == + GRPC_CHANNEL_IDLE); +} + +/* Test and use the "num_external_watchers" call to make sure + * that "connectivity watcher" structs are free'd just after, if + * their corresponding timeouts occur. */ +static void run_timeouts_test(const test_fixture *fixture) { + gpr_log(GPR_INFO, "TEST: %s", fixture->name); + + char *addr; + + grpc_init(); + + gpr_join_host_port(&addr, "localhost", grpc_pick_unused_port_or_die()); + + grpc_channel *channel = fixture->create_channel(addr); + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + + /* start 1 watcher and then let it time out */ + channel_idle_start_watch(channel, cq); + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 1); + channel_idle_poll_for_timeout(channel, cq); + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); + + /* start 3 watchers and then let them all time out */ + for (size_t i = 1; i <= 3; i++) { + channel_idle_start_watch(channel, cq); + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == + (int)i); + } + for (size_t i = 1; i <= 3; i++) { + channel_idle_poll_for_timeout(channel, cq); + } + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); + + /* start 3 watchers, see one time out, start another 3, and then see them all + * time out */ + for (size_t i = 1; i <= 3; i++) { + channel_idle_start_watch(channel, cq); + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == + (int)i); + } + channel_idle_poll_for_timeout(channel, cq); + for (size_t i = 3; i <= 5; i++) { + channel_idle_start_watch(channel, cq); + } + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) >= 3); + for (size_t i = 1; i <= 5; i++) { + channel_idle_poll_for_timeout(channel, cq); + } + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); + + grpc_channel_destroy(channel); + grpc_completion_queue_shutdown(cq); + GPR_ASSERT( + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) + .type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cq); + + grpc_shutdown(); + gpr_free(addr); +} + +/* An edge scenario; sets channel state to explicitly, and outside + * of a polling call. */ +static void run_channel_shutdown_before_timeout_test( + const test_fixture *fixture) { + gpr_log(GPR_INFO, "TEST: %s", fixture->name); + + char *addr; + + grpc_init(); + + gpr_join_host_port(&addr, "localhost", grpc_pick_unused_port_or_die()); + + grpc_channel *channel = fixture->create_channel(addr); + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + + /* start 1 watcher and then shut down the channel before the timer goes off */ + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); + + /* expecting a 30 second timeout to go off much later than the shutdown. */ + gpr_timespec connect_deadline = grpc_timeout_seconds_to_deadline(30); + GPR_ASSERT(grpc_channel_check_connectivity_state(channel, 0) == + GRPC_CHANNEL_IDLE); + + grpc_channel_watch_connectivity_state(channel, GRPC_CHANNEL_IDLE, + connect_deadline, cq, (void *)1); + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 1); + grpc_channel_destroy(channel); + + grpc_event ev = + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + /* expect success with a state transition to CHANNEL_SHUTDOWN */ + GPR_ASSERT(ev.success == true); + + grpc_completion_queue_shutdown(cq); + GPR_ASSERT( + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL) + .type == GRPC_QUEUE_SHUTDOWN); + grpc_completion_queue_destroy(cq); + + grpc_shutdown(); + gpr_free(addr); +} + +static grpc_channel *insecure_test_create_channel(const char *addr) { + return grpc_insecure_channel_create(addr, NULL, NULL); +} + +static const test_fixture insecure_test = { + "insecure", insecure_test_create_channel, +}; + +static grpc_channel *secure_test_create_channel(const char *addr) { + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(test_root_cert, NULL, NULL); + grpc_arg ssl_name_override = {GRPC_ARG_STRING, + GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, + {"foo.test.google.fr"}}; + grpc_channel_args *new_client_args = + grpc_channel_args_copy_and_add(NULL, &ssl_name_override, 1); + grpc_channel *channel = + grpc_secure_channel_create(ssl_creds, addr, new_client_args, NULL); + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, new_client_args); + grpc_exec_ctx_finish(&exec_ctx); + } + grpc_channel_credentials_release(ssl_creds); + return channel; +} + +static const test_fixture secure_test = { + "secure", secure_test_create_channel, +}; + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + + run_timeouts_test(&insecure_test); + run_timeouts_test(&secure_test); + + run_channel_shutdown_before_timeout_test(&insecure_test); + run_channel_shutdown_before_timeout_test(&secure_test); +} diff --git a/test/core/surface/sequential_connectivity_test.c b/test/core/surface/sequential_connectivity_test.c index 5f66f90037..8a6dd69c0f 100644 --- a/test/core/surface/sequential_connectivity_test.c +++ b/test/core/surface/sequential_connectivity_test.c @@ -99,6 +99,9 @@ static void run_test(const test_fixture *fixture) { connect_deadline, cq, NULL); grpc_event ev = grpc_completion_queue_next( cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + /* check that the watcher from "watch state" was free'd */ + GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channels[i]) == + 0); GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); GPR_ASSERT(ev.tag == NULL); GPR_ASSERT(ev.success == true); diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index f5653d6f9e..5afeed3d25 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1689,6 +1689,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "num_external_connectivity_watchers_test", + "src": [ + "test/core/surface/num_external_connectivity_watchers_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index a08caf30d3..7e350990c9 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1763,6 +1763,30 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "gtest": false, + "language": "c", + "name": "num_external_connectivity_watchers_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index c8fcacf75b..9cb966de48 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -1284,6 +1284,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "no_server_test", "vcxproj\t {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "num_external_connectivity_watchers_test", "vcxproj\test\num_external_connectivity_watchers_test\num_external_connectivity_watchers_test.vcxproj", "{4E856E4A-7497-1B1A-1AED-D4C01E5D873A}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "parse_address_test", "vcxproj\test\parse_address_test\parse_address_test.vcxproj", "{EDEA8257-AEA8-1B0A-F95B-8D6CD7286463}" ProjectSection(myProperties) = preProject lib = "False" @@ -3577,6 +3588,22 @@ Global {A66AC548-E2B9-74CD-293C-43526EE51DCE}.Release-DLL|Win32.Build.0 = Release|Win32 {A66AC548-E2B9-74CD-293C-43526EE51DCE}.Release-DLL|x64.ActiveCfg = Release|x64 {A66AC548-E2B9-74CD-293C-43526EE51DCE}.Release-DLL|x64.Build.0 = Release|x64 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Debug|Win32.ActiveCfg = Debug|Win32 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Debug|x64.ActiveCfg = Debug|x64 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Release|Win32.ActiveCfg = Release|Win32 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Release|x64.ActiveCfg = Release|x64 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Debug|Win32.Build.0 = Debug|Win32 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Debug|x64.Build.0 = Debug|x64 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Release|Win32.Build.0 = Release|Win32 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Release|x64.Build.0 = Release|x64 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Debug-DLL|x64.Build.0 = Debug|x64 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Release-DLL|Win32.Build.0 = Release|Win32 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Release-DLL|x64.ActiveCfg = Release|x64 + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A}.Release-DLL|x64.Build.0 = Release|x64 {EDEA8257-AEA8-1B0A-F95B-8D6CD7286463}.Debug|Win32.ActiveCfg = Debug|Win32 {EDEA8257-AEA8-1B0A-F95B-8D6CD7286463}.Debug|x64.ActiveCfg = Debug|x64 {EDEA8257-AEA8-1B0A-F95B-8D6CD7286463}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/test/num_external_connectivity_watchers_test/num_external_connectivity_watchers_test.vcxproj b/vsprojects/vcxproj/test/num_external_connectivity_watchers_test/num_external_connectivity_watchers_test.vcxproj new file mode 100644 index 0000000000..2b373e8a16 --- /dev/null +++ b/vsprojects/vcxproj/test/num_external_connectivity_watchers_test/num_external_connectivity_watchers_test.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {4E856E4A-7497-1B1A-1AED-D4C01E5D873A} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + num_external_connectivity_watchers_test + static + Debug + static + Debug + + + num_external_connectivity_watchers_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/num_external_connectivity_watchers_test/num_external_connectivity_watchers_test.vcxproj.filters b/vsprojects/vcxproj/test/num_external_connectivity_watchers_test/num_external_connectivity_watchers_test.vcxproj.filters new file mode 100644 index 0000000000..92a4198e30 --- /dev/null +++ b/vsprojects/vcxproj/test/num_external_connectivity_watchers_test/num_external_connectivity_watchers_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\surface + + + + + + {9557f01e-947a-775e-4540-bf9a1fd9b19a} + + + {2b3a6de2-5820-e21f-5b39-66012c94bfbb} + + + {e3f23659-fc16-a4cc-a9e2-c73b625c38f5} + + + + -- cgit v1.2.3 From c0ce2cdf0030dd5df342fda3c3e76afccacaa854 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Fri, 19 May 2017 17:47:49 -0700 Subject: Update version to 1.3.5 --- BUILD | 2 +- CMakeLists.txt | 2 +- Makefile | 4 ++-- build.yaml | 2 +- gRPC-Core.podspec | 2 +- gRPC-ProtoRPC.podspec | 2 +- gRPC-RxLibrary.podspec | 2 +- gRPC.podspec | 2 +- package.json | 2 +- package.xml | 4 ++-- src/cpp/common/version_cc.cc | 2 +- src/csharp/Grpc.Core/Version.csproj.include | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 4 ++-- src/csharp/build_packages_dotnetcli.bat | 2 +- src/csharp/build_packages_dotnetcli.sh | 4 ++-- src/node/health_check/package.json | 4 ++-- src/node/tools/package.json | 2 +- src/objective-c/!ProtoCompiler-gRPCPlugin.podspec | 2 +- src/objective-c/GRPCClient/private/version.h | 2 +- src/php/composer.json | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/python/grpcio_health_checking/grpc_version.py | 2 +- src/python/grpcio_reflection/grpc_version.py | 2 +- src/python/grpcio_tests/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- 29 files changed, 34 insertions(+), 34 deletions(-) diff --git a/BUILD b/BUILD index 51314f645c..166e6ba751 100644 --- a/BUILD +++ b/BUILD @@ -42,7 +42,7 @@ g_stands_for = "gentle" core_version = "3.0.0" -version = "1.3.4" +version = "1.3.5" grpc_cc_library( name = "gpr", diff --git a/CMakeLists.txt b/CMakeLists.txt index 48f9bb42a9..cff8f856e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.3.4") +set(PACKAGE_VERSION "1.3.5") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") diff --git a/Makefile b/Makefile index 8359ce2fc6..77206ba92b 100644 --- a/Makefile +++ b/Makefile @@ -420,8 +420,8 @@ Q = @ endif CORE_VERSION = 3.0.0 -CPP_VERSION = 1.3.4 -CSHARP_VERSION = 1.3.4 +CPP_VERSION = 1.3.5 +CSHARP_VERSION = 1.3.5 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/build.yaml b/build.yaml index 0629b459ac..3af590609a 100644 --- a/build.yaml +++ b/build.yaml @@ -14,7 +14,7 @@ settings: '#10': See the expand_version.py for all the quirks here core_version: 3.0.0 g_stands_for: gentle - version: 1.3.4 + version: 1.3.5 filegroups: - name: census public_headers: diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index c8e50b577a..5d1ba61183 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -37,7 +37,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.3.4' + version = '1.3.5' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'http://www.grpc.io' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 6737e0136a..e60ea7c08e 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.3.4' + version = '1.3.5' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'http://www.grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 0b338d44aa..d82130ad4a 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.3.4' + version = '1.3.5' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'http://www.grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index 1783df67ef..5aa8a86a05 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -35,7 +35,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.3.4' + version = '1.3.5' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'http://www.grpc.io' diff --git a/package.json b/package.json index 11e3441652..c83f51c221 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "1.3.4", + "version": "1.3.5", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", diff --git a/package.xml b/package.xml index 6b3eddadf6..1c91f1c0c2 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2017-05-05 - 1.3.4 - 1.3.4 + 1.3.5 + 1.3.5 beta diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index 97437ba530..0a1b72527b 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -37,5 +37,5 @@ #include namespace grpc { -grpc::string Version() { return "1.3.4"; } +grpc::string Version() { return "1.3.5"; } } diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 881c311b17..63536ecc6b 100755 --- a/src/csharp/Grpc.Core/Version.csproj.include +++ b/src/csharp/Grpc.Core/Version.csproj.include @@ -1,7 +1,7 @@ - 1.3.4 + 1.3.5 3.2.0 diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index bbe5a17d6b..fed38292f0 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -48,11 +48,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "1.3.4.0"; + public const string CurrentAssemblyFileVersion = "1.3.5.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "1.3.4"; + public const string CurrentVersion = "1.3.5"; } } diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index a385ac74e3..3aec7aacbe 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -28,7 +28,7 @@ @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem Current package versions -set VERSION=1.3.4 +set VERSION=1.3.5 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh index 66c41d4d94..da585cb663 100755 --- a/src/csharp/build_packages_dotnetcli.sh +++ b/src/csharp/build_packages_dotnetcli.sh @@ -70,7 +70,7 @@ dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts -nuget pack Grpc.nuspec -Version "1.3.4" -OutputDirectory ../../artifacts -nuget pack Grpc.Tools.nuspec -Version "1.3.4" -OutputDirectory ../../artifacts +nuget pack Grpc.nuspec -Version "1.3.5" -OutputDirectory ../../artifacts +nuget pack Grpc.Tools.nuspec -Version "1.3.5" -OutputDirectory ../../artifacts (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg) diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json index 6329cd9c37..2fdcb12777 100644 --- a/src/node/health_check/package.json +++ b/src/node/health_check/package.json @@ -1,6 +1,6 @@ { "name": "grpc-health-check", - "version": "1.3.4", + "version": "1.3.5", "author": "Google Inc.", "description": "Health check service for use with gRPC", "repository": { @@ -15,7 +15,7 @@ } ], "dependencies": { - "grpc": "^1.3.4", + "grpc": "^1.3.5", "lodash": "^3.9.3", "google-protobuf": "^3.0.0" }, diff --git a/src/node/tools/package.json b/src/node/tools/package.json index 355ae2fdc1..cabd4030dc 100644 --- a/src/node/tools/package.json +++ b/src/node/tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "1.3.4", + "version": "1.3.5", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "http://www.grpc.io/", diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index b4fc968504..23f91867c4 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.3.4' + v = '1.3.5' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index ccf96230bc..43ab9bd064 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -38,4 +38,4 @@ // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.3.4" +#define GRPC_OBJC_VERSION_STRING @"1.3.5" diff --git a/src/php/composer.json b/src/php/composer.json index 562859e6b3..08f2b9afab 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "BSD-3-Clause", - "version": "1.3.4", + "version": "1.3.5", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.1.0" diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 29ffcab106..52b1397468 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION='1.3.4' +VERSION='1.3.5' diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index 16e0dc1327..143c1ede36 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION='1.3.4' +VERSION='1.3.5' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index 5ef0ed8045..66f1ff968a 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION='1.3.4' +VERSION='1.3.5' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index 7e4c57e6ec..a6da39c8eb 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION='1.3.4' +VERSION='1.3.5' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index c03ec97196..27595318d3 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.3.4' + VERSION = '1.3.5' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index fe0fb2cef2..f93c1f14af 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -29,6 +29,6 @@ module GRPC module Tools - VERSION = '1.3.4' + VERSION = '1.3.5' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index 020785aa73..7178681329 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION='1.3.4' +VERSION='1.3.5' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 5021a1a153..55980eadac 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.3.4 +PROJECT_NUMBER = 1.3.5 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 1df6951aef..7580617bf1 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.3.4 +PROJECT_NUMBER = 1.3.5 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a -- cgit v1.2.3 From 8f7bc54ff2256179ede6d4a6d1a8792b7820fc28 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Tue, 16 May 2017 10:30:59 -0700 Subject: Reconnect disconnected channels automatically --- src/python/grpcio/grpc/_channel.py | 7 ++- src/python/grpcio_tests/tests/tests.json | 1 + .../grpcio_tests/tests/unit/_reconnect_test.py | 70 ++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/python/grpcio_tests/tests/unit/_reconnect_test.py diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py index 4316449ac6..012ed8ec81 100644 --- a/src/python/grpcio/grpc/_channel.py +++ b/src/python/grpcio/grpc/_channel.py @@ -786,7 +786,7 @@ def _channel_managed_call_management(state): class _ChannelConnectivityState(object): def __init__(self, channel): - self.lock = threading.Lock() + self.lock = threading.RLock() self.channel = channel self.polling = False self.connectivity = None @@ -926,6 +926,11 @@ class Channel(grpc.Channel): self._call_state = _ChannelCallState(self._channel) self._connectivity_state = _ChannelConnectivityState(self._channel) + # TODO(https://github.com/grpc/grpc/issues/9884) + # Temporary work around UNAVAILABLE issues + # Remove this once c-core has retry support + _subscribe(self._connectivity_state, lambda *args: None, None) + def subscribe(self, callback, try_to_connect=None): _subscribe(self._connectivity_state, callback, try_to_connect) diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json index f750b05102..5f641d8701 100644 --- a/src/python/grpcio_tests/tests/tests.json +++ b/src/python/grpcio_tests/tests/tests.json @@ -31,6 +31,7 @@ "unit._invocation_defects_test.InvocationDefectsTest", "unit._metadata_code_details_test.MetadataCodeDetailsTest", "unit._metadata_test.MetadataTest", + "unit._reconnect_test.ReconnectTest", "unit._resource_exhausted_test.ResourceExhaustedTest", "unit._rpc_test.RPCTest", "unit._sanity._sanity_test.Sanity", diff --git a/src/python/grpcio_tests/tests/unit/_reconnect_test.py b/src/python/grpcio_tests/tests/unit/_reconnect_test.py new file mode 100644 index 0000000000..6c316476b3 --- /dev/null +++ b/src/python/grpcio_tests/tests/unit/_reconnect_test.py @@ -0,0 +1,70 @@ +# Copyright 2017, 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. +"""Tests that a channel will reconnect if a connection is dropped""" + +import unittest + +import grpc +from grpc.framework.foundation import logging_pool + +from tests.unit.framework.common import test_constants + +_REQUEST = b'\x00\x00\x00' +_RESPONSE = b'\x00\x00\x01' + +_UNARY_UNARY = '/test/UnaryUnary' + + +def _handle_unary_unary(unused_request, unused_servicer_context): + return _RESPONSE + + +class ReconnectTest(unittest.TestCase): + + def test_reconnect(self): + server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + handler = grpc.method_handlers_generic_handler('test', { + 'UnaryUnary': + grpc.unary_unary_rpc_method_handler(_handle_unary_unary) + }) + server = grpc.server(server_pool, (handler,)) + port = server.add_insecure_port('[::]:0') + server.start() + channel = grpc.insecure_channel('localhost:%d' % port) + multi_callable = channel.unary_unary(_UNARY_UNARY) + self.assertEqual(_RESPONSE, multi_callable(_REQUEST)) + server.stop(None) + server = grpc.server(server_pool, (handler,)) + server.add_insecure_port('[::]:{}'.format(port)) + server.start() + self.assertEqual(_RESPONSE, multi_callable(_REQUEST)) + + +if __name__ == '__main__': + unittest.main(verbosity=2) -- cgit v1.2.3 From c91bc02d979c30da40b67204324f28b569a3c8b6 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 14:49:26 +0200 Subject: Add Grpc.Microbenchmarks project --- src/csharp/Grpc.Microbenchmarks/.gitignore | 2 + .../Grpc.Microbenchmarks.csproj | 28 ++++++++++++++ src/csharp/Grpc.Microbenchmarks/Program.cs | 45 ++++++++++++++++++++++ src/csharp/Grpc.sln | 8 +++- 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/csharp/Grpc.Microbenchmarks/.gitignore create mode 100644 src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj create mode 100644 src/csharp/Grpc.Microbenchmarks/Program.cs diff --git a/src/csharp/Grpc.Microbenchmarks/.gitignore b/src/csharp/Grpc.Microbenchmarks/.gitignore new file mode 100644 index 0000000000..1746e3269e --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj b/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj new file mode 100644 index 0000000000..26a940e488 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/Grpc.Microbenchmarks.csproj @@ -0,0 +1,28 @@ + + + + + + + net45;netcoreapp1.0 + Grpc.Microbenchmarks + Exe + Grpc.Microbenchmarks + $(PackageTargetFallback);portable-net45 + 1.0.4 + + + + + + + + + + + + + + + + diff --git a/src/csharp/Grpc.Microbenchmarks/Program.cs b/src/csharp/Grpc.Microbenchmarks/Program.cs new file mode 100644 index 0000000000..ac577d1b98 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/Program.cs @@ -0,0 +1,45 @@ +#region Copyright notice and license + +// 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. + +#endregion + +using System; + +namespace Grpc.Microbenchmarks +{ + class Program + { + public static void Main(string[] args) + { + Console.WriteLine("Helloworld"); + } + } +} diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln index beab3ccb36..d9a7b8d556 100644 --- a/src/csharp/Grpc.sln +++ b/src/csharp/Grpc.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.4 +VisualStudioVersion = 15.0.26430.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core", "Grpc.Core\Grpc.Core.csproj", "{BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}" EndProject @@ -37,6 +37,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Reflection", "Grpc.Ref EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.csproj", "{335AD0A2-F2CC-4C2E-853C-26174206BEE7}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Microbenchmarks", "Grpc.Microbenchmarks\Grpc.Microbenchmarks.csproj", "{84C17746-4727-4290-8E8B-A380793DAE1E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -111,6 +113,10 @@ Global {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Debug|Any CPU.Build.0 = Debug|Any CPU {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Release|Any CPU.ActiveCfg = Release|Any CPU {335AD0A2-F2CC-4C2E-853C-26174206BEE7}.Release|Any CPU.Build.0 = Release|Any CPU + {84C17746-4727-4290-8E8B-A380793DAE1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84C17746-4727-4290-8E8B-A380793DAE1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84C17746-4727-4290-8E8B-A380793DAE1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84C17746-4727-4290-8E8B-A380793DAE1E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- cgit v1.2.3 From ff5f9d898f5ab2c49a0be09de33c8e2f80a6b785 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 14:51:42 +0200 Subject: make internals visible to microbenchmarks --- src/csharp/Grpc.Core/Properties/AssemblyInfo.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs index 77ac347c7d..fe757820fd 100644 --- a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs +++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs @@ -59,8 +59,14 @@ using System.Runtime.CompilerServices; "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Microbenchmarks,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] #else [assembly: InternalsVisibleTo("Grpc.Core.Tests")] [assembly: InternalsVisibleTo("Grpc.Core.Testing")] [assembly: InternalsVisibleTo("Grpc.IntegrationTesting")] +[assembly: InternalsVisibleTo("Grpc.Microbenchmarks")] #endif -- cgit v1.2.3 From c7c2bf171414d577d0df336059ff5732b2c0ca4a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 15:01:43 +0200 Subject: add editorconfig for C# --- src/csharp/.editorconfig | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/csharp/.editorconfig diff --git a/src/csharp/.editorconfig b/src/csharp/.editorconfig new file mode 100644 index 0000000000..7bc2bcce18 --- /dev/null +++ b/src/csharp/.editorconfig @@ -0,0 +1,7 @@ +root = true +[**] +end_of_line = LF +indent_style = space +indent_size = 4 +insert_final_newline = true +tab_width = 4 -- cgit v1.2.3 From 7cc83c8cd5772aff3033e4aafaa05cd2bdaa068a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 15:51:23 +0200 Subject: allow creating fake CallSafeHandle --- src/csharp/Grpc.Core/Internal/CallSafeHandle.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index 8ed0c0b92f..bc74e212b1 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -218,5 +218,16 @@ namespace Grpc.Core.Internal { return buffered ? 0 : GRPC_WRITE_BUFFER_HINT; } + + /// + /// Only for testing. + /// + public static CallSafeHandle CreateFake(IntPtr ptr, CompletionQueueSafeHandle cq) + { + var call = new CallSafeHandle(); + call.SetHandle(ptr); + call.Initialize(cq); + return call; + } } } -- cgit v1.2.3 From e58842f33a988c8691d1591c970b4b1232021432 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 19 May 2017 15:52:05 +0200 Subject: benchmark prototype --- .../Grpc.Core/Internal/CompletionRegistry.cs | 7 ++ src/csharp/Grpc.Microbenchmarks/Program.cs | 10 +- .../Grpc.Microbenchmarks/SendMessageBenchmark.cs | 106 +++++++++++++++++++++ .../Grpc.Microbenchmarks/ThreadedBenchmark.cs | 79 +++++++++++++++ 4 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs diff --git a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs index a4aa8d3ffe..fc0ff72e6a 100644 --- a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs +++ b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs @@ -52,6 +52,7 @@ namespace Grpc.Core.Internal readonly GrpcEnvironment environment; readonly ConcurrentDictionary dict = new ConcurrentDictionary(new IntPtrComparer()); + IntPtr lastRegisteredKey; public CompletionRegistry(GrpcEnvironment environment) { @@ -62,6 +63,7 @@ namespace Grpc.Core.Internal { environment.DebugStats.PendingBatchCompletions.Increment(); GrpcPreconditions.CheckState(dict.TryAdd(key, callback)); + this.lastRegisteredKey = key; } public void RegisterBatchCompletion(BatchContextSafeHandle ctx, BatchCompletionDelegate callback) @@ -84,6 +86,11 @@ namespace Grpc.Core.Internal return value; } + public IntPtr LastRegisteredKey + { + get { return this.lastRegisteredKey; } + } + private static void HandleBatchCompletion(bool success, BatchContextSafeHandle ctx, BatchCompletionDelegate callback) { try diff --git a/src/csharp/Grpc.Microbenchmarks/Program.cs b/src/csharp/Grpc.Microbenchmarks/Program.cs index ac577d1b98..09b6eb68d9 100644 --- a/src/csharp/Grpc.Microbenchmarks/Program.cs +++ b/src/csharp/Grpc.Microbenchmarks/Program.cs @@ -32,6 +32,8 @@ #endregion using System; +using Grpc.Core; +using Grpc.Core.Internal; namespace Grpc.Microbenchmarks { @@ -39,7 +41,13 @@ namespace Grpc.Microbenchmarks { public static void Main(string[] args) { - Console.WriteLine("Helloworld"); + var benchmark = new SendMessageBenchmark(); + benchmark.Init(); + foreach (int threadCount in new int[] {1, 1, 2, 4, 8, 12}) + { + benchmark.Run(threadCount, 4 * 1000 * 1000, 0); + } + benchmark.Cleanup(); } } } diff --git a/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs new file mode 100644 index 0000000000..4575529bef --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs @@ -0,0 +1,106 @@ +#region Copyright notice and license + +// 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. + +#endregion + +using System; +using System.Threading; +using Grpc.Core; +using Grpc.Core.Internal; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Grpc.Microbenchmarks +{ + public class SendMessageBenchmark + { + static readonly NativeMethods Native = NativeMethods.Get(); + + GrpcEnvironment environment; + + public void Init() + { + Native.grpcsharp_test_override_method("grpcsharp_call_start_batch", "nop"); + environment = GrpcEnvironment.AddRef(); + } + + public void Cleanup() + { + GrpcEnvironment.ReleaseAsync().Wait(); + // TODO(jtattermusch): track GC stats + } + + public void Run(int threadCount, int iterations, int payloadSize) + { + Console.WriteLine(string.Format("SendMessageBenchmark: threads={0}, iterations={1}, payloadSize={2}", threadCount, iterations, payloadSize)); + var threadedBenchmark = new ThreadedBenchmark(threadCount, () => ThreadBody(iterations, payloadSize)); + threadedBenchmark.Run(); + } + + private void ThreadBody(int iterations, int payloadSize) + { + // TODO(jtattermusch): parametrize by number of pending completions. + // TODO(jtattermusch): parametrize by cached/non-cached BatchContextSafeHandle + + var completionRegistry = new CompletionRegistry(environment); + var cq = CompletionQueueSafeHandle.CreateAsync(completionRegistry); + var call = CreateFakeCall(cq); + + var sendCompletionHandler = new SendCompletionHandler((success) => { }); + var payload = new byte[payloadSize]; + var writeFlags = default(WriteFlags); + + var stopwatch = Stopwatch.StartNew(); + for (int i = 0; i < iterations; i++) + { + call.StartSendMessage(sendCompletionHandler, payload, writeFlags, false); + var callback = completionRegistry.Extract(completionRegistry.LastRegisteredKey); + callback(); + } + stopwatch.Stop(); + Console.WriteLine("Elapsed millis: " + stopwatch.ElapsedMilliseconds); + + cq.Dispose(); + } + + private static CallSafeHandle CreateFakeCall(CompletionQueueSafeHandle cq) + { + var call = CallSafeHandle.CreateFake(new IntPtr(0xdead), cq); + bool success = false; + while (!success) + { + // avoid calling destroy on a nonexistent grpc_call pointer + call.DangerousAddRef(ref success); + } + return call; + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs new file mode 100644 index 0000000000..1c54624034 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/ThreadedBenchmark.cs @@ -0,0 +1,79 @@ +#region Copyright notice and license + +// 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. + +#endregion + +using System; +using System.Threading; +using Grpc.Core; +using Grpc.Core.Internal; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Grpc.Microbenchmarks +{ + public class ThreadedBenchmark + { + List runners; + + public ThreadedBenchmark(IEnumerable runners) + { + this.runners = new List(runners); + } + + public ThreadedBenchmark(int threadCount, Action threadBody) + { + this.runners = new List(); + for (int i = 0; i < threadCount; i++) + { + this.runners.Add(new ThreadStart(() => threadBody())); + } + } + + public void Run() + { + Console.WriteLine("Running threads."); + var threads = new List(); + for (int i = 0; i < runners.Count; i++) + { + var thread = new Thread(runners[i]); + thread.Start(); + threads.Add(thread); + } + + foreach (var thread in threads) + { + thread.Join(); + } + Console.WriteLine("All threads finished."); + } + } +} -- cgit v1.2.3 From 645ae74e88c73492ac3a98e5bf16ea24600e5a65 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 22 May 2017 08:46:26 -0700 Subject: overridable call_start_batch --- src/csharp/Grpc.Core/Internal/NativeMethods.cs | 4 ++ src/csharp/Grpc.Microbenchmarks/Program.cs | 2 + src/csharp/ext/grpc_csharp_ext.c | 65 +++++++++++++++++++++----- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs index 696987d2a8..5ce792d296 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -164,6 +164,8 @@ namespace Grpc.Core.Internal public readonly Delegates.grpcsharp_test_callback_delegate grpcsharp_test_callback; public readonly Delegates.grpcsharp_test_nop_delegate grpcsharp_test_nop; + public readonly Delegates.grpcsharp_test_override_method_delegate grpcsharp_test_override_method; + #endregion public NativeMethods(UnmanagedLibrary library) @@ -278,6 +280,7 @@ namespace Grpc.Core.Internal this.grpcsharp_test_callback = GetMethodDelegate(library); this.grpcsharp_test_nop = GetMethodDelegate(library); + this.grpcsharp_test_override_method = GetMethodDelegate(library); } /// @@ -434,6 +437,7 @@ namespace Grpc.Core.Internal public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr); + public delegate void grpcsharp_test_override_method(string methodName, string variant); } } } diff --git a/src/csharp/Grpc.Microbenchmarks/Program.cs b/src/csharp/Grpc.Microbenchmarks/Program.cs index 09b6eb68d9..a0ca1f75ae 100644 --- a/src/csharp/Grpc.Microbenchmarks/Program.cs +++ b/src/csharp/Grpc.Microbenchmarks/Program.cs @@ -34,6 +34,7 @@ using System; using Grpc.Core; using Grpc.Core.Internal; +using Grpc.Core.Logging; namespace Grpc.Microbenchmarks { @@ -41,6 +42,7 @@ namespace Grpc.Microbenchmarks { public static void Main(string[] args) { + GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); var benchmark = new SendMessageBenchmark(); benchmark.Init(); foreach (int threadCount in new int[] {1, 1, 2, 4, 8, 12}) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index f6cff454bd..34f8b928dd 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -529,6 +529,31 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) { grpc_call_unref(call); } +typedef grpc_call_error (*grpcsharp_call_start_batch_func) ( + grpc_call *call, const grpc_op *ops, size_t nops, + void *tag, void *reserved); + +/* Only for testing */ +static grpc_call_error grpcsharp_call_start_batch_nop( + grpc_call *call, const grpc_op *ops, size_t nops, + void *tag, void *reserved) { + return GRPC_CALL_OK; +} + +static grpc_call_error grpcsharp_call_start_batch_default( + grpc_call *call, const grpc_op *ops, size_t nops, + void *tag, void *reserved) { + return grpc_call_start_batch(call, ops, nops, tag, reserved); +} + +static grpcsharp_call_start_batch_func g_call_start_batch_func = grpcsharp_call_start_batch_default; + +static grpc_call_error grpcsharp_call_start_batch( + grpc_call *call, const grpc_op *ops, size_t nops, + void *tag, void *reserved) { + return g_call_start_batch_func(call, ops, nops, tag, reserved); +} + GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary( grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer, size_t send_buffer_len, uint32_t write_flags, @@ -576,7 +601,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary( ops[5].flags = 0; ops[5].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -616,7 +641,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming( ops[3].flags = 0; ops[3].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -656,7 +681,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( ops[3].flags = 0; ops[3].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -685,7 +710,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming( ops[1].flags = 0; ops[1].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -699,7 +724,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata( ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -720,7 +745,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message( ops[1].flags = 0; ops[1].reserved = NULL; - return grpc_call_start_batch(call, ops, nops, ctx, NULL); + return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client( @@ -731,7 +756,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client( ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -773,7 +798,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server( ops[nops].reserved = NULL; nops++; } - return grpc_call_start_batch(call, ops, nops, ctx, NULL); + return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE @@ -784,7 +809,7 @@ grpcsharp_call_recv_message(grpc_call *call, grpcsharp_batch_context *ctx) { ops[0].data.recv_message.recv_message = &(ctx->recv_message); ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -798,7 +823,7 @@ grpcsharp_call_start_serverside(grpc_call *call, grpcsharp_batch_context *ctx) { ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -817,7 +842,7 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata( ops[0].flags = 0; ops[0].reserved = NULL; - return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, NULL); } @@ -1092,3 +1117,21 @@ GPR_EXPORT void *GPR_CALLTYPE grpcsharp_test_nop(void *ptr) { return ptr; } GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) { return sizeof(grpc_event); } + +/* Override a method for testing */ +GPR_EXPORT void GPR_CALLTYPE grpcsharp_test_override_method(const char *method_name, + const char *variant) { + if (strcmp("grpcsharp_call_start_batch", method_name) == 0) + { + if (strcmp("nop", variant) == 0) + { + g_call_start_batch_func = grpcsharp_call_start_batch_nop; + } else { + GPR_ASSERT(0); + } + } else { + GPR_ASSERT(0); + } +} + + -- cgit v1.2.3 From 7c206f4c154c0897898042060cf0be481995e131 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 22 May 2017 09:23:18 -0700 Subject: override in benchmark --- src/csharp/Grpc.Core/Internal/NativeMethods.cs | 2 +- src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs index 5ce792d296..e703e3e6ce 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -437,7 +437,7 @@ namespace Grpc.Core.Internal public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr); - public delegate void grpcsharp_test_override_method(string methodName, string variant); + public delegate void grpcsharp_test_override_method_delegate(string methodName, string variant); } } } diff --git a/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs index 4575529bef..eea375824f 100644 --- a/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs +++ b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs @@ -83,7 +83,7 @@ namespace Grpc.Microbenchmarks { call.StartSendMessage(sendCompletionHandler, payload, writeFlags, false); var callback = completionRegistry.Extract(completionRegistry.LastRegisteredKey); - callback(); + callback(true); } stopwatch.Stop(); Console.WriteLine("Elapsed millis: " + stopwatch.ElapsedMilliseconds); -- cgit v1.2.3 From 254ab4c085ae39c0935b06edccfffdaeaeda94a1 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 23 May 2017 18:07:17 +0200 Subject: clang format code --- src/csharp/ext/grpc_csharp_ext.c | 81 +++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 34f8b928dd..a56113eca3 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -529,28 +529,35 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) { grpc_call_unref(call); } -typedef grpc_call_error (*grpcsharp_call_start_batch_func) ( - grpc_call *call, const grpc_op *ops, size_t nops, - void *tag, void *reserved); +typedef grpc_call_error (*grpcsharp_call_start_batch_func)(grpc_call *call, + const grpc_op *ops, + size_t nops, + void *tag, + void *reserved); /* Only for testing */ -static grpc_call_error grpcsharp_call_start_batch_nop( - grpc_call *call, const grpc_op *ops, size_t nops, - void *tag, void *reserved) { +static grpc_call_error grpcsharp_call_start_batch_nop(grpc_call *call, + const grpc_op *ops, + size_t nops, void *tag, + void *reserved) { return GRPC_CALL_OK; } -static grpc_call_error grpcsharp_call_start_batch_default( - grpc_call *call, const grpc_op *ops, size_t nops, - void *tag, void *reserved) { +static grpc_call_error grpcsharp_call_start_batch_default(grpc_call *call, + const grpc_op *ops, + size_t nops, + void *tag, + void *reserved) { return grpc_call_start_batch(call, ops, nops, tag, reserved); } -static grpcsharp_call_start_batch_func g_call_start_batch_func = grpcsharp_call_start_batch_default; +static grpcsharp_call_start_batch_func g_call_start_batch_func = + grpcsharp_call_start_batch_default; -static grpc_call_error grpcsharp_call_start_batch( - grpc_call *call, const grpc_op *ops, size_t nops, - void *tag, void *reserved) { +static grpc_call_error grpcsharp_call_start_batch(grpc_call *call, + const grpc_op *ops, + size_t nops, void *tag, + void *reserved) { return g_call_start_batch_func(call, ops, nops, tag, reserved); } @@ -601,8 +608,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary( ops[5].flags = 0; ops[5].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming( @@ -641,8 +648,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming( ops[3].flags = 0; ops[3].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( @@ -681,8 +688,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( ops[3].flags = 0; ops[3].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming( @@ -710,8 +717,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming( ops[1].flags = 0; ops[1].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata( @@ -724,8 +731,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata( ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message( @@ -756,8 +763,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client( ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server( @@ -809,8 +816,8 @@ grpcsharp_call_recv_message(grpc_call *call, grpcsharp_batch_context *ctx) { ops[0].data.recv_message.recv_message = &(ctx->recv_message); ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE @@ -823,8 +830,8 @@ grpcsharp_call_start_serverside(grpc_call *call, grpcsharp_batch_context *ctx) { ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata( @@ -842,8 +849,8 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata( ops[0].flags = 0; ops[0].reserved = NULL; - return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx, - NULL); + return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), + ctx, NULL); } GPR_EXPORT grpc_call_error GPR_CALLTYPE @@ -1119,12 +1126,10 @@ GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) { } /* Override a method for testing */ -GPR_EXPORT void GPR_CALLTYPE grpcsharp_test_override_method(const char *method_name, - const char *variant) { - if (strcmp("grpcsharp_call_start_batch", method_name) == 0) - { - if (strcmp("nop", variant) == 0) - { +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_test_override_method(const char *method_name, const char *variant) { + if (strcmp("grpcsharp_call_start_batch", method_name) == 0) { + if (strcmp("nop", variant) == 0) { g_call_start_batch_func = grpcsharp_call_start_batch_nop; } else { GPR_ASSERT(0); @@ -1133,5 +1138,3 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_test_override_method(const char *method_n GPR_ASSERT(0); } } - - -- cgit v1.2.3 From f8be2d65cc942e94c81d76e1fba5bb3aee538189 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 23 May 2017 21:08:34 +0200 Subject: add privateassets none to C# nugets depending on Grpc.Core --- src/csharp/Grpc.Auth/Grpc.Auth.csproj | 4 +++- src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj | 6 ++++-- src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj | 4 +++- src/csharp/Grpc.Reflection/Grpc.Reflection.csproj | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj index 6ac25aa1f0..c082e30c46 100755 --- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj +++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj @@ -23,7 +23,9 @@ - + + None + diff --git a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj index f4dd5105fc..1efda925bd 100755 --- a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj +++ b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj @@ -1,4 +1,4 @@ - + @@ -23,7 +23,9 @@ - + + None + diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj index eac6e1fc95..80c7dfe48c 100755 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj @@ -22,7 +22,9 @@ - + + None + diff --git a/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj index 70bfcc89c5..eafa0f4e10 100755 --- a/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj +++ b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj @@ -22,7 +22,9 @@ - + + None + -- cgit v1.2.3 From be8522974d9a8237468193d680b20cb503793a57 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 23 May 2017 22:17:22 +0200 Subject: include symbols and source in nugets --- src/csharp/Grpc.Auth/Grpc.Auth.csproj | 2 ++ src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj | 2 ++ src/csharp/Grpc.Core/Grpc.Core.csproj | 4 +++- src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj | 2 ++ src/csharp/Grpc.Reflection/Grpc.Reflection.csproj | 2 ++ 5 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj index c082e30c46..188ddb95b9 100755 --- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj +++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj @@ -16,6 +16,8 @@ https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 + true + true diff --git a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj index 1efda925bd..45ec874322 100755 --- a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj +++ b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj @@ -16,6 +16,8 @@ https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 + true + true diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 7e0f3f053d..bcf0282b92 100755 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -1,4 +1,4 @@ - + @@ -15,6 +15,8 @@ https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 + true + true diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj index 80c7dfe48c..c3791a4e6b 100755 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj @@ -15,6 +15,8 @@ https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 + true + true diff --git a/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj index eafa0f4e10..3a07555248 100755 --- a/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj +++ b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj @@ -15,6 +15,8 @@ https://github.com/grpc/grpc https://github.com/grpc/grpc/blob/master/LICENSE 1.6.0 + true + true -- cgit v1.2.3 From 905f41869bbf143ccf38f3aa4ed6980251ad7de3 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 23 May 2017 22:34:14 +0200 Subject: remove now unnecessary extra args --- src/csharp/build_packages_dotnetcli.bat | 10 +++++----- src/csharp/build_packages_dotnetcli.sh | 10 +++++----- templates/src/csharp/build_packages_dotnetcli.bat.template | 10 +++++----- templates/src/csharp/build_packages_dotnetcli.sh.template | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index 3aec7aacbe..eb3ba2a952 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -60,11 +60,11 @@ xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* pr @rem To be able to build, we also need to put grpc_csharp_ext to its normal location xcopy /Y /I nativelibs\windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release\ -%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core --output ..\..\..\artifacts || goto :error -%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ..\..\..\artifacts || goto :error -%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Auth --output ..\..\..\artifacts || goto :error -%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ..\..\..\artifacts || goto :error -%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ..\..\..\artifacts || goto :error +%DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error +%DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error +%DOTNET% pack --configuration Release Grpc.Auth --output ..\..\..\artifacts || goto :error +%DOTNET% pack --configuration Release Grpc.HealthCheck --output ..\..\..\artifacts || goto :error +%DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error %NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error %NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh index da585cb663..76ae99a2fb 100755 --- a/src/csharp/build_packages_dotnetcli.sh +++ b/src/csharp/build_packages_dotnetcli.sh @@ -64,11 +64,11 @@ dotnet restore Grpc.sln mkdir -p ../../libs/opt cp nativelibs/linux_x64/libgrpc_csharp_ext.so ../../libs/opt -dotnet pack --configuration Release --include-symbols --include-source Grpc.Core --output ../../../artifacts -dotnet pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ../../../artifacts -dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth --output ../../../artifacts -dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts -dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts +dotnet pack --configuration Release Grpc.Core --output ../../../artifacts +dotnet pack --configuration Release Grpc.Core.Testing --output ../../../artifacts +dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts +dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts +dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts nuget pack Grpc.nuspec -Version "1.3.5" -OutputDirectory ../../artifacts nuget pack Grpc.Tools.nuspec -Version "1.3.5" -OutputDirectory ../../artifacts diff --git a/templates/src/csharp/build_packages_dotnetcli.bat.template b/templates/src/csharp/build_packages_dotnetcli.bat.template index 5f6ffb9754..91808e0d26 100755 --- a/templates/src/csharp/build_packages_dotnetcli.bat.template +++ b/templates/src/csharp/build_packages_dotnetcli.bat.template @@ -62,11 +62,11 @@ @rem To be able to build, we also need to put grpc_csharp_ext to its normal location xcopy /Y /I nativelibs\windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release${"\\"} - %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Auth --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ..\..\..\artifacts || goto :error + %%DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error + %%DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error + %%DOTNET% pack --configuration Release Grpc.Auth --output ..\..\..\artifacts || goto :error + %%DOTNET% pack --configuration Release Grpc.HealthCheck --output ..\..\..\artifacts || goto :error + %%DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error %%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error %%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts diff --git a/templates/src/csharp/build_packages_dotnetcli.sh.template b/templates/src/csharp/build_packages_dotnetcli.sh.template index d37f4eb4f4..374b236f93 100755 --- a/templates/src/csharp/build_packages_dotnetcli.sh.template +++ b/templates/src/csharp/build_packages_dotnetcli.sh.template @@ -66,11 +66,11 @@ mkdir -p ../../libs/opt cp nativelibs/linux_x64/libgrpc_csharp_ext.so ../../libs/opt - dotnet pack --configuration Release --include-symbols --include-source Grpc.Core --output ../../../artifacts - dotnet pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ../../../artifacts - dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth --output ../../../artifacts - dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts - dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts + dotnet pack --configuration Release Grpc.Core --output ../../../artifacts + dotnet pack --configuration Release Grpc.Core.Testing --output ../../../artifacts + dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts + dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts + dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts nuget pack Grpc.nuspec -Version "${settings.csharp_version}" -OutputDirectory ../../artifacts nuget pack Grpc.Tools.nuspec -Version "${settings.csharp_version}" -OutputDirectory ../../artifacts -- cgit v1.2.3 From bbfdbb19c002d23e2fd3d94d6a089cff5b03a390 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 23 May 2017 22:48:45 +0200 Subject: bump version to 1.3.6 --- BUILD | 2 +- CMakeLists.txt | 2 +- Makefile | 4 ++-- build.yaml | 2 +- gRPC-Core.podspec | 2 +- gRPC-ProtoRPC.podspec | 2 +- gRPC-RxLibrary.podspec | 2 +- gRPC.podspec | 2 +- package.json | 2 +- package.xml | 4 ++-- src/cpp/common/version_cc.cc | 2 +- src/csharp/Grpc.Core/Version.csproj.include | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 4 ++-- src/csharp/build_packages_dotnetcli.bat | 2 +- src/csharp/build_packages_dotnetcli.sh | 4 ++-- src/node/health_check/package.json | 4 ++-- src/node/tools/package.json | 2 +- src/objective-c/!ProtoCompiler-gRPCPlugin.podspec | 2 +- src/objective-c/GRPCClient/private/version.h | 2 +- src/php/composer.json | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/python/grpcio_health_checking/grpc_version.py | 2 +- src/python/grpcio_reflection/grpc_version.py | 2 +- src/python/grpcio_tests/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- 29 files changed, 34 insertions(+), 34 deletions(-) diff --git a/BUILD b/BUILD index 166e6ba751..cb8c08a636 100644 --- a/BUILD +++ b/BUILD @@ -42,7 +42,7 @@ g_stands_for = "gentle" core_version = "3.0.0" -version = "1.3.5" +version = "1.3.6" grpc_cc_library( name = "gpr", diff --git a/CMakeLists.txt b/CMakeLists.txt index cff8f856e0..86416cc11e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.3.5") +set(PACKAGE_VERSION "1.3.6") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") diff --git a/Makefile b/Makefile index 77206ba92b..b5bb74113b 100644 --- a/Makefile +++ b/Makefile @@ -420,8 +420,8 @@ Q = @ endif CORE_VERSION = 3.0.0 -CPP_VERSION = 1.3.5 -CSHARP_VERSION = 1.3.5 +CPP_VERSION = 1.3.6 +CSHARP_VERSION = 1.3.6 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/build.yaml b/build.yaml index 3af590609a..4c01cf245d 100644 --- a/build.yaml +++ b/build.yaml @@ -14,7 +14,7 @@ settings: '#10': See the expand_version.py for all the quirks here core_version: 3.0.0 g_stands_for: gentle - version: 1.3.5 + version: 1.3.6 filegroups: - name: census public_headers: diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 5d1ba61183..515a8dad63 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -37,7 +37,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.3.5' + version = '1.3.6' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'http://www.grpc.io' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index e60ea7c08e..d4dd0b1044 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.3.5' + version = '1.3.6' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'http://www.grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index d82130ad4a..6ed1849f02 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.3.5' + version = '1.3.6' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'http://www.grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index 5aa8a86a05..808bbf92e8 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -35,7 +35,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.3.5' + version = '1.3.6' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'http://www.grpc.io' diff --git a/package.json b/package.json index c83f51c221..b8ac31aa55 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "1.3.5", + "version": "1.3.6", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", diff --git a/package.xml b/package.xml index 1c91f1c0c2..66e313b1a4 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2017-05-05 - 1.3.5 - 1.3.5 + 1.3.6 + 1.3.6 beta diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index 0a1b72527b..7101842346 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -37,5 +37,5 @@ #include namespace grpc { -grpc::string Version() { return "1.3.5"; } +grpc::string Version() { return "1.3.6"; } } diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 63536ecc6b..22d7b92ae3 100755 --- a/src/csharp/Grpc.Core/Version.csproj.include +++ b/src/csharp/Grpc.Core/Version.csproj.include @@ -1,7 +1,7 @@ - 1.3.5 + 1.3.6 3.2.0 diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index fed38292f0..fb6a4b4197 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -48,11 +48,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "1.3.5.0"; + public const string CurrentAssemblyFileVersion = "1.3.6.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "1.3.5"; + public const string CurrentVersion = "1.3.6"; } } diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index 3aec7aacbe..1f93ff694f 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -28,7 +28,7 @@ @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem Current package versions -set VERSION=1.3.5 +set VERSION=1.3.6 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh index da585cb663..9f467fcbe6 100755 --- a/src/csharp/build_packages_dotnetcli.sh +++ b/src/csharp/build_packages_dotnetcli.sh @@ -70,7 +70,7 @@ dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts -nuget pack Grpc.nuspec -Version "1.3.5" -OutputDirectory ../../artifacts -nuget pack Grpc.Tools.nuspec -Version "1.3.5" -OutputDirectory ../../artifacts +nuget pack Grpc.nuspec -Version "1.3.6" -OutputDirectory ../../artifacts +nuget pack Grpc.Tools.nuspec -Version "1.3.6" -OutputDirectory ../../artifacts (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg) diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json index 2fdcb12777..f5700206fd 100644 --- a/src/node/health_check/package.json +++ b/src/node/health_check/package.json @@ -1,6 +1,6 @@ { "name": "grpc-health-check", - "version": "1.3.5", + "version": "1.3.6", "author": "Google Inc.", "description": "Health check service for use with gRPC", "repository": { @@ -15,7 +15,7 @@ } ], "dependencies": { - "grpc": "^1.3.5", + "grpc": "^1.3.6", "lodash": "^3.9.3", "google-protobuf": "^3.0.0" }, diff --git a/src/node/tools/package.json b/src/node/tools/package.json index cabd4030dc..59397a5c24 100644 --- a/src/node/tools/package.json +++ b/src/node/tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "1.3.5", + "version": "1.3.6", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "http://www.grpc.io/", diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 23f91867c4..0d14df62df 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.3.5' + v = '1.3.6' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index 43ab9bd064..578d31c9ed 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -38,4 +38,4 @@ // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.3.5" +#define GRPC_OBJC_VERSION_STRING @"1.3.6" diff --git a/src/php/composer.json b/src/php/composer.json index 08f2b9afab..45be98eba3 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "BSD-3-Clause", - "version": "1.3.5", + "version": "1.3.6", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.1.0" diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 52b1397468..1997ce98fa 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION='1.3.5' +VERSION='1.3.6' diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index 143c1ede36..4e4ddd5e2d 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION='1.3.5' +VERSION='1.3.6' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index 66f1ff968a..de61ce0ab2 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION='1.3.5' +VERSION='1.3.6' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index a6da39c8eb..b07ec7946d 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION='1.3.5' +VERSION='1.3.6' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 27595318d3..3973654d5f 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.3.5' + VERSION = '1.3.6' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index f93c1f14af..1650938cda 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -29,6 +29,6 @@ module GRPC module Tools - VERSION = '1.3.5' + VERSION = '1.3.6' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index 7178681329..3e94e82a6d 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION='1.3.5' +VERSION='1.3.6' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 55980eadac..c8a2a9f01c 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.3.5 +PROJECT_NUMBER = 1.3.6 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 7580617bf1..d09757c2b1 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.3.5 +PROJECT_NUMBER = 1.3.6 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a -- cgit v1.2.3 From 30f2b7ece1d04502ef9a4345b88a76844ced9f2c Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 25 May 2017 10:55:53 -0700 Subject: Add more null checks to call methods --- src/node/ext/call.cc | 20 +++++++++++++++++--- src/node/ext/call.h | 1 + src/node/test/common_test.js | 1 - src/node/test/surface_test.js | 25 +++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 2cc9f63b65..e2185da1c5 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -562,10 +562,12 @@ void Call::DestroyCall() { Call::Call(grpc_call *call) : wrapped_call(call), pending_batches(0), has_final_op_completed(false) { + peer = grpc_call_get_peer(call); } Call::~Call() { DestroyCall(); + gpr_free(peer); } void Call::Init(Local exports) { @@ -794,6 +796,11 @@ NAN_METHOD(Call::Cancel) { return Nan::ThrowTypeError("cancel can only be called on Call objects"); } Call *call = ObjectWrap::Unwrap(info.This()); + if (call->wrapped_call == NULL) { + /* Cancel is supposed to be idempotent. If the call has already finished, + * cancel should just complete silently */ + return; + } grpc_call_error error = grpc_call_cancel(call->wrapped_call, NULL); if (error != GRPC_CALL_OK) { return Nan::ThrowError(nanErrorWithCode("cancel failed", error)); @@ -814,6 +821,11 @@ NAN_METHOD(Call::CancelWithStatus) { "cancelWithStatus's second argument must be a string"); } Call *call = ObjectWrap::Unwrap(info.This()); + if (call->wrapped_call == NULL) { + /* Cancel is supposed to be idempotent. If the call has already finished, + * cancel should just complete silently */ + return; + } grpc_status_code code = static_cast( Nan::To(info[0]).FromJust()); if (code == GRPC_STATUS_OK) { @@ -830,9 +842,7 @@ NAN_METHOD(Call::GetPeer) { return Nan::ThrowTypeError("getPeer can only be called on Call objects"); } Call *call = ObjectWrap::Unwrap(info.This()); - char *peer = grpc_call_get_peer(call->wrapped_call); - Local peer_value = Nan::New(peer).ToLocalChecked(); - gpr_free(peer); + Local peer_value = Nan::New(call->peer).ToLocalChecked(); info.GetReturnValue().Set(peer_value); } @@ -847,6 +857,10 @@ NAN_METHOD(Call::SetCredentials) { "setCredentials' first argument must be a CallCredentials"); } Call *call = ObjectWrap::Unwrap(info.This()); + if (call->wrapped_call == NULL) { + return Nan::ThrowError( + "Cannot set credentials on a call that has already started"); + } CallCredentials *creds_object = ObjectWrap::Unwrap( Nan::To(info[0]).ToLocalChecked()); grpc_call_credentials *creds = creds_object->GetWrappedCredentials(); diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 340e32682b..45b448e0b1 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -97,6 +97,7 @@ class Call : public Nan::ObjectWrap { call, this is GRPC_OP_RECV_STATUS_ON_CLIENT and for a server call, this is GRPC_OP_SEND_STATUS_FROM_SERVER */ bool has_final_op_completed; + char *peer; }; class Op { diff --git a/src/node/test/common_test.js b/src/node/test/common_test.js index b7c2c6a8d6..db80207e22 100644 --- a/src/node/test/common_test.js +++ b/src/node/test/common_test.js @@ -100,7 +100,6 @@ describe('Proto message long int serialize and deserialize', function() { var longNumDeserialize = deserializeCls(messages_proto.LongValues, num_options); var serialized = longSerialize({int_64: pos_value}); - console.log(longDeserialize(serialized)); assert.strictEqual(typeof longDeserialize(serialized).int_64, 'string'); /* With the longsAsStrings option disabled, long values are represented as * objects with 3 keys: low, high, and unsigned */ diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index d2f0511af2..0696e7ae19 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -1110,6 +1110,18 @@ describe('Other conditions', function() { done(); }); }); + it('after the call has fully completed', function(done) { + var peer; + var call = client.unary({error: false}, function(err, data) { + assert.ifError(err); + setImmediate(function() { + assert.strictEqual(peer, call.getPeer()); + done(); + }); + }); + peer = call.getPeer(); + assert.strictEqual(typeof peer, 'string'); + }); }); }); describe('Call propagation', function() { @@ -1352,4 +1364,17 @@ describe('Cancelling surface client', function() { }); call.cancel(); }); + it('Should be idempotent', function(done) { + var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) { + assert.strictEqual(err.code, surface_client.status.CANCELLED); + // Call asynchronously to try cancelling after call is fully completed + setImmediate(function() { + assert.doesNotThrow(function() { + call.cancel(); + }); + done(); + }); + }); + call.cancel(); + }); }); -- cgit v1.2.3 From cd6ab2212252db6543291121699451a9285a0c9a Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 25 May 2017 15:45:32 -0700 Subject: Fix concurrent_connectivity_test --- test/core/surface/concurrent_connectivity_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c index 1f09311b1f..7614696cae 100644 --- a/test/core/surface/concurrent_connectivity_test.c +++ b/test/core/surface/concurrent_connectivity_test.c @@ -254,7 +254,7 @@ int run_concurrent_connectivity_test() { void watches_with_short_timeouts(void *addr) { for (int i = 0; i < NUM_OUTER_LOOPS_SHORT_TIMEOUTS; ++i) { - grpc_completion_queue *cq = grpc_completion_queue_create(NULL); + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL); for (int j = 0; j < NUM_INNER_LOOPS_SHORT_TIMEOUTS; ++j) { -- cgit v1.2.3 From 7563641414f490f0f66a6991fc3901319ddb172c Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 25 May 2017 16:36:01 -0700 Subject: Fix node cancellation tests --- src/node/test/surface_test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index 0696e7ae19..f8eaf62aaf 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -1334,14 +1334,14 @@ describe('Cancelling surface client', function() { }); it('Should correctly cancel a unary call', function(done) { var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) { - assert.strictEqual(err.code, surface_client.status.CANCELLED); + assert.strictEqual(err.code, grpc.status.CANCELLED); done(); }); call.cancel(); }); it('Should correctly cancel a client stream call', function(done) { var call = client.sum(function(err, resp) { - assert.strictEqual(err.code, surface_client.status.CANCELLED); + assert.strictEqual(err.code, grpc.status.CANCELLED); done(); }); call.cancel(); @@ -1350,7 +1350,7 @@ describe('Cancelling surface client', function() { var call = client.fib({'limit': 5}); call.on('data', function() {}); call.on('error', function(error) { - assert.strictEqual(error.code, surface_client.status.CANCELLED); + assert.strictEqual(error.code, grpc.status.CANCELLED); done(); }); call.cancel(); @@ -1359,14 +1359,14 @@ describe('Cancelling surface client', function() { var call = client.divMany(); call.on('data', function() {}); call.on('error', function(error) { - assert.strictEqual(error.code, surface_client.status.CANCELLED); + assert.strictEqual(error.code, grpc.status.CANCELLED); done(); }); call.cancel(); }); it('Should be idempotent', function(done) { var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) { - assert.strictEqual(err.code, surface_client.status.CANCELLED); + assert.strictEqual(err.code, grpc.status.CANCELLED); // Call asynchronously to try cancelling after call is fully completed setImmediate(function() { assert.doesNotThrow(function() { -- cgit v1.2.3 From ce0861185b3c282b5a1ea1b31f51a96285315f84 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 25 May 2017 21:41:37 -0700 Subject: add missing copyright headers --- src/core/ext/census/intrusive_hash_map.c | 37 +++++++++++++++------ src/core/ext/census/intrusive_hash_map.h | 37 +++++++++++++++------ src/core/ext/census/intrusive_hash_map_internal.h | 39 ++++++++++++++++------- test/core/census/intrusive_hash_map_test.c | 37 +++++++++++++++------ 4 files changed, 109 insertions(+), 41 deletions(-) diff --git a/src/core/ext/census/intrusive_hash_map.c b/src/core/ext/census/intrusive_hash_map.c index e64e8086ca..77512a3aac 100644 --- a/src/core/ext/census/intrusive_hash_map.c +++ b/src/core/ext/census/intrusive_hash_map.c @@ -1,17 +1,34 @@ /* - * Copyright 2017 Google Inc. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Copyright 2017, Google Inc. + * All rights reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "src/core/ext/census/intrusive_hash_map.h" diff --git a/src/core/ext/census/intrusive_hash_map.h b/src/core/ext/census/intrusive_hash_map.h index 9a7fd07f20..a759306058 100644 --- a/src/core/ext/census/intrusive_hash_map.h +++ b/src/core/ext/census/intrusive_hash_map.h @@ -1,17 +1,34 @@ /* - * Copyright 2017 Google Inc. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Copyright 2017, Google Inc. + * All rights reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H diff --git a/src/core/ext/census/intrusive_hash_map_internal.h b/src/core/ext/census/intrusive_hash_map_internal.h index c0a3c6f59a..625c06c841 100644 --- a/src/core/ext/census/intrusive_hash_map_internal.h +++ b/src/core/ext/census/intrusive_hash_map_internal.h @@ -1,17 +1,34 @@ /* - * Copyright 2017 Google Inc. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Copyright 2017, Google Inc. + * All rights reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H @@ -43,4 +60,4 @@ typedef struct intrusive_hash_map { chunked_vector buckets; } intrusive_hash_map; -#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H +#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H diff --git a/test/core/census/intrusive_hash_map_test.c b/test/core/census/intrusive_hash_map_test.c index a0a46ebadf..fe8d3a1675 100644 --- a/test/core/census/intrusive_hash_map_test.c +++ b/test/core/census/intrusive_hash_map_test.c @@ -1,17 +1,34 @@ /* - * Copyright 2017 Google Inc. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Copyright 2017, Google Inc. + * All rights reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include "src/core/ext/census/intrusive_hash_map.h" -- cgit v1.2.3 From e809bca022c5f2f72015db56250fdab19d2a4cbc Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 25 May 2017 21:42:04 -0700 Subject: rerun clang format code.sh --- src/core/ext/census/intrusive_hash_map.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/census/intrusive_hash_map.h b/src/core/ext/census/intrusive_hash_map.h index a759306058..b898f45e90 100644 --- a/src/core/ext/census/intrusive_hash_map.h +++ b/src/core/ext/census/intrusive_hash_map.h @@ -164,4 +164,4 @@ void intrusive_hash_map_clear(intrusive_hash_map *hash_map, void intrusive_hash_map_free(intrusive_hash_map *hash_map, void (*free_object)(void *)); -#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H +#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H -- cgit v1.2.3 From 4d381910d00f4e764edf9d308960f2563c323d02 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 25 May 2017 22:06:44 -0700 Subject: fix format of include guards --- src/core/ext/census/intrusive_hash_map.h | 2 +- src/core/ext/census/intrusive_hash_map_internal.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ext/census/intrusive_hash_map.h b/src/core/ext/census/intrusive_hash_map.h index b898f45e90..a8405517b8 100644 --- a/src/core/ext/census/intrusive_hash_map.h +++ b/src/core/ext/census/intrusive_hash_map.h @@ -164,4 +164,4 @@ void intrusive_hash_map_clear(intrusive_hash_map *hash_map, void intrusive_hash_map_free(intrusive_hash_map *hash_map, void (*free_object)(void *)); -#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H +#endif /* GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H */ diff --git a/src/core/ext/census/intrusive_hash_map_internal.h b/src/core/ext/census/intrusive_hash_map_internal.h index 625c06c841..76a9a3a722 100644 --- a/src/core/ext/census/intrusive_hash_map_internal.h +++ b/src/core/ext/census/intrusive_hash_map_internal.h @@ -60,4 +60,4 @@ typedef struct intrusive_hash_map { chunked_vector buckets; } intrusive_hash_map; -#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H +#endif /* GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H */ -- cgit v1.2.3 From 342e72c585315e6f6e74e1412b3d58cd746ec89f Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 26 May 2017 07:44:03 -0400 Subject: Remove uneeded ref/unref --- src/core/lib/http/httpcli.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c index f5588a9a76..7012ffe568 100644 --- a/src/core/lib/http/httpcli.c +++ b/src/core/lib/http/httpcli.c @@ -105,7 +105,7 @@ static void finish(grpc_exec_ctx *exec_ctx, internal_request *req, grpc_error *error) { grpc_polling_entity_del_from_pollset_set(exec_ctx, req->pollent, req->context->pollset_set); - grpc_closure_sched(exec_ctx, req->on_done, GRPC_ERROR_REF(error)); + grpc_closure_sched(exec_ctx, req->on_done, error); grpc_http_parser_destroy(&req->parser); if (req->addresses != NULL) { grpc_resolved_addresses_destroy(req->addresses); @@ -120,7 +120,6 @@ static void finish(grpc_exec_ctx *exec_ctx, internal_request *req, grpc_slice_buffer_destroy_internal(exec_ctx, &req->incoming); grpc_slice_buffer_destroy_internal(exec_ctx, &req->outgoing); GRPC_ERROR_UNREF(req->overall_error); - GRPC_ERROR_UNREF(error); grpc_resource_quota_unref_internal(exec_ctx, req->resource_quota); gpr_free(req); } -- cgit v1.2.3 From 46356b72a011e02e7bd59bc390d358b887e84e7e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 26 May 2017 15:22:08 +0000 Subject: Make jobset more eintr resilient --- tools/run_tests/python_utils/jobset.py | 62 +++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py index 3754035308..3ff773300f 100755 --- a/tools/run_tests/python_utils/jobset.py +++ b/tools/run_tests/python_utils/jobset.py @@ -41,6 +41,7 @@ import subprocess import sys import tempfile import time +import errno # cpu cost measurement @@ -132,29 +133,44 @@ _TAG_COLOR = { _FORMAT = '%(asctime)-15s %(message)s' logging.basicConfig(level=logging.INFO, format=_FORMAT) + +def eintr_be_gone(fn): + """Run fn until it doesn't stop because of EINTR""" + while True: + try: + return fn() + except IOError, e: + if e.errno != errno.EINTR: + raise + + + def message(tag, msg, explanatory_text=None, do_newline=False): if message.old_tag == tag and message.old_msg == msg and not explanatory_text: return message.old_tag = tag message.old_msg = msg - try: - if platform_string() == 'windows' or not sys.stdout.isatty(): - if explanatory_text: - logging.info(explanatory_text) - logging.info('%s: %s', tag, msg) - else: - sys.stdout.write('%s%s%s\x1b[%d;%dm%s\x1b[0m: %s%s' % ( - _BEGINNING_OF_LINE, - _CLEAR_LINE, - '\n%s' % explanatory_text if explanatory_text is not None else '', - _COLORS[_TAG_COLOR[tag]][1], - _COLORS[_TAG_COLOR[tag]][0], - tag, - msg, - '\n' if do_newline or explanatory_text is not None else '')) - sys.stdout.flush() - except: - pass + while True: + try: + if platform_string() == 'windows' or not sys.stdout.isatty(): + if explanatory_text: + logging.info(explanatory_text) + logging.info('%s: %s', tag, msg) + else: + sys.stdout.write('%s%s%s\x1b[%d;%dm%s\x1b[0m: %s%s' % ( + _BEGINNING_OF_LINE, + _CLEAR_LINE, + '\n%s' % explanatory_text if explanatory_text is not None else '', + _COLORS[_TAG_COLOR[tag]][1], + _COLORS[_TAG_COLOR[tag]][0], + tag, + msg, + '\n' if do_newline or explanatory_text is not None else '')) + sys.stdout.flush() + return + except IOError, e: + if e.errno != errno.EINTR: + raise message.old_tag = '' message.old_msg = '' @@ -226,16 +242,6 @@ class JobResult(object): self.cpu_measured = 0 -def eintr_be_gone(fn): - """Run fn until it doesn't stop because of EINTR""" - while True: - try: - return fn() - except IOError, e: - if e.errno != errno.EINTR: - raise - - def read_from_start(f): f.seek(0) return f.read() -- cgit v1.2.3 From e22c902e6304f944463ea4a26a9733361f2c5314 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Fri, 26 May 2017 08:45:48 -0700 Subject: clang-format and include guard fix --- src/core/ext/census/intrusive_hash_map.h | 2 +- src/core/ext/census/intrusive_hash_map_internal.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ext/census/intrusive_hash_map.h b/src/core/ext/census/intrusive_hash_map.h index 9a7fd07f20..cb31cf6510 100644 --- a/src/core/ext/census/intrusive_hash_map.h +++ b/src/core/ext/census/intrusive_hash_map.h @@ -147,4 +147,4 @@ void intrusive_hash_map_clear(intrusive_hash_map *hash_map, void intrusive_hash_map_free(intrusive_hash_map *hash_map, void (*free_object)(void *)); -#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H +#endif /* GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H */ diff --git a/src/core/ext/census/intrusive_hash_map_internal.h b/src/core/ext/census/intrusive_hash_map_internal.h index c0a3c6f59a..dba190cce5 100644 --- a/src/core/ext/census/intrusive_hash_map_internal.h +++ b/src/core/ext/census/intrusive_hash_map_internal.h @@ -43,4 +43,4 @@ typedef struct intrusive_hash_map { chunked_vector buckets; } intrusive_hash_map; -#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H +#endif /* GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H */ -- cgit v1.2.3 From cce3ccc29ede38276628060ab9b819dbeaafe23f Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Fri, 26 May 2017 14:10:13 -0700 Subject: get rid of flakey asserts in num_watchers test --- test/core/surface/num_external_connectivity_watchers_test.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/core/surface/num_external_connectivity_watchers_test.c b/test/core/surface/num_external_connectivity_watchers_test.c index 96288ab60d..93944c9ad5 100644 --- a/test/core/surface/num_external_connectivity_watchers_test.c +++ b/test/core/surface/num_external_connectivity_watchers_test.c @@ -92,15 +92,12 @@ static void run_timeouts_test(const test_fixture *fixture) { /* start 1 watcher and then let it time out */ channel_idle_start_watch(channel, cq); - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 1); channel_idle_poll_for_timeout(channel, cq); GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 0); /* start 3 watchers and then let them all time out */ for (size_t i = 1; i <= 3; i++) { channel_idle_start_watch(channel, cq); - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == - (int)i); } for (size_t i = 1; i <= 3; i++) { channel_idle_poll_for_timeout(channel, cq); @@ -111,14 +108,11 @@ static void run_timeouts_test(const test_fixture *fixture) { * time out */ for (size_t i = 1; i <= 3; i++) { channel_idle_start_watch(channel, cq); - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == - (int)i); } channel_idle_poll_for_timeout(channel, cq); for (size_t i = 3; i <= 5; i++) { channel_idle_start_watch(channel, cq); } - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) >= 3); for (size_t i = 1; i <= 5; i++) { channel_idle_poll_for_timeout(channel, cq); } @@ -160,7 +154,6 @@ static void run_channel_shutdown_before_timeout_test( grpc_channel_watch_connectivity_state(channel, GRPC_CHANNEL_IDLE, connect_deadline, cq, (void *)1); - GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(channel) == 1); grpc_channel_destroy(channel); grpc_event ev = -- cgit v1.2.3 From c400cc5f8dcff7ff70a7030f085ebdd5c9359fa5 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 26 May 2017 14:44:34 -0700 Subject: address comments --- src/csharp/Grpc.Core/Internal/CompletionRegistry.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs index fc0ff72e6a..075286d33e 100644 --- a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs +++ b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs @@ -52,7 +52,7 @@ namespace Grpc.Core.Internal readonly GrpcEnvironment environment; readonly ConcurrentDictionary dict = new ConcurrentDictionary(new IntPtrComparer()); - IntPtr lastRegisteredKey; + IntPtr lastRegisteredKey; // only for testing public CompletionRegistry(GrpcEnvironment environment) { @@ -86,6 +86,9 @@ namespace Grpc.Core.Internal return value; } + /// + /// For testing purposes only. + /// public IntPtr LastRegisteredKey { get { return this.lastRegisteredKey; } -- cgit v1.2.3 From 93fdf611a571450964ad4512ff2ed33d7c39c47c Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Tue, 30 May 2017 14:03:01 -0700 Subject: s/inline/__inline/. Visual studio incompatiblity. MS Visual studio '13 and before don't understand inline and throw Error C2054. Reference: https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx --- src/core/ext/census/intrusive_hash_map.c | 10 +++++----- src/core/ext/census/intrusive_hash_map.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/ext/census/intrusive_hash_map.c b/src/core/ext/census/intrusive_hash_map.c index 77512a3aac..d147f23364 100644 --- a/src/core/ext/census/intrusive_hash_map.c +++ b/src/core/ext/census/intrusive_hash_map.c @@ -37,7 +37,7 @@ extern bool hm_index_compare(const hm_index *A, const hm_index *B); /* Simple hashing function that takes lower 32 bits. */ -static inline uint32_t chunked_vector_hasher(uint64_t key) { +static __inline uint32_t chunked_vector_hasher(uint64_t key) { return (uint32_t)key; } @@ -45,7 +45,7 @@ static inline uint32_t chunked_vector_hasher(uint64_t key) { static const size_t VECTOR_CHUNK_SIZE = (1 << 20) / sizeof(void *); /* Helper functions which return buckets from the chunked vector. */ -static inline void **get_mutable_bucket(const chunked_vector *buckets, +static __inline void **get_mutable_bucket(const chunked_vector *buckets, uint32_t index) { if (index < VECTOR_CHUNK_SIZE) { return &buckets->first_[index]; @@ -54,7 +54,7 @@ static inline void **get_mutable_bucket(const chunked_vector *buckets, return &buckets->rest_[rest_index][index % VECTOR_CHUNK_SIZE]; } -static inline void *get_bucket(const chunked_vector *buckets, uint32_t index) { +static __inline void *get_bucket(const chunked_vector *buckets, uint32_t index) { if (index < VECTOR_CHUNK_SIZE) { return buckets->first_[index]; } @@ -63,7 +63,7 @@ static inline void *get_bucket(const chunked_vector *buckets, uint32_t index) { } /* Helper function. */ -static inline size_t RestSize(const chunked_vector *vec) { +static __inline size_t RestSize(const chunked_vector *vec) { return (vec->size_ <= VECTOR_CHUNK_SIZE) ? 0 : (vec->size_ - VECTOR_CHUNK_SIZE - 1) / VECTOR_CHUNK_SIZE + 1; @@ -222,7 +222,7 @@ hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key) { * array_size-1. Returns true if it is a new hm_item and false if the hm_item * already existed. */ -static inline bool intrusive_hash_map_internal_insert(chunked_vector *buckets, +static __inline bool intrusive_hash_map_internal_insert(chunked_vector *buckets, uint32_t hash_mask, hm_item *item) { const uint64_t key = item->key; diff --git a/src/core/ext/census/intrusive_hash_map.h b/src/core/ext/census/intrusive_hash_map.h index a8405517b8..e316bf4b16 100644 --- a/src/core/ext/census/intrusive_hash_map.h +++ b/src/core/ext/census/intrusive_hash_map.h @@ -101,7 +101,7 @@ typedef struct hm_index { /* Returns true if two hm_indices point to the same object within the hash map * and false otherwise. */ -inline bool hm_index_compare(const hm_index *A, const hm_index *B) { +__inline bool hm_index_compare(const hm_index *A, const hm_index *B) { return (A->item == B->item && A->bucket_index == B->bucket_index); } -- cgit v1.2.3 From aebcdbd732e9294c8a424d3167c028f02af5ef1c Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Tue, 30 May 2017 14:14:27 -0700 Subject: master bumped to 1.5.x --- BUILD | 4 ++-- CMakeLists.txt | 2 +- Makefile | 4 ++-- build.yaml | 2 +- gRPC-Core.podspec | 2 +- gRPC-ProtoRPC.podspec | 2 +- gRPC-RxLibrary.podspec | 2 +- gRPC.podspec | 2 +- package.json | 2 +- package.xml | 4 ++-- src/cpp/common/version_cc.cc | 2 +- src/csharp/Grpc.Core/Version.csproj.include | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 4 ++-- src/csharp/build_packages_dotnetcli.bat | 2 +- src/csharp/build_packages_dotnetcli.sh | 4 ++-- src/node/health_check/package.json | 4 ++-- src/node/tools/package.json | 2 +- src/objective-c/!ProtoCompiler-gRPCPlugin.podspec | 2 +- src/objective-c/GRPCClient/private/version.h | 2 +- src/php/composer.json | 2 +- src/php/ext/grpc/version.h | 2 +- src/python/grpcio/grpc/_grpcio_metadata.py | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/python/grpcio_health_checking/grpc_version.py | 2 +- src/python/grpcio_reflection/grpc_version.py | 2 +- src/python/grpcio_tests/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- 31 files changed, 37 insertions(+), 37 deletions(-) diff --git a/BUILD b/BUILD index bdea522ad1..d3a77808ea 100644 --- a/BUILD +++ b/BUILD @@ -51,9 +51,9 @@ load( # This should be updated along with build.yaml g_stands_for = "gregarious" -core_version = "3.0.0-dev" +core_version = "4.0.0-dev" -version = "1.4.0-dev" +version = "1.5.0-dev" grpc_cc_library( name = "gpr", diff --git a/CMakeLists.txt b/CMakeLists.txt index fd53f621a6..11c6b04788 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.4.0-dev") +set(PACKAGE_VERSION "1.5.0-dev") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") diff --git a/Makefile b/Makefile index 82b2104b4a..5e29711fb1 100644 --- a/Makefile +++ b/Makefile @@ -423,8 +423,8 @@ Q = @ endif CORE_VERSION = 4.0.0-dev -CPP_VERSION = 1.4.0-dev -CSHARP_VERSION = 1.4.0-dev +CPP_VERSION = 1.5.0-dev +CSHARP_VERSION = 1.5.0-dev CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/build.yaml b/build.yaml index 26144e33de..d1e61256e6 100644 --- a/build.yaml +++ b/build.yaml @@ -14,7 +14,7 @@ settings: '#10': See the expand_version.py for all the quirks here core_version: 4.0.0-dev g_stands_for: gregarious - version: 1.4.0-dev + version: 1.5.0-dev filegroups: - name: census public_headers: diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index d9de2d78a0..e5e61df477 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -37,7 +37,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.4.0-dev' + version = '1.5.0-dev' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'http://www.grpc.io' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 62cb0d11a1..6baef28885 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.4.0-dev' + version = '1.5.0-dev' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'http://www.grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 77ceb22123..dfccc5d16c 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.4.0-dev' + version = '1.5.0-dev' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'http://www.grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index 10520bd388..7f4886ab65 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -35,7 +35,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.4.0-dev' + version = '1.5.0-dev' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'http://www.grpc.io' diff --git a/package.json b/package.json index 1ed182ced9..a0d76c435b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "1.4.0-dev", + "version": "1.5.0-dev", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", diff --git a/package.xml b/package.xml index 9179ef238c..817a0345d6 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2017-05-22 - 1.4.0dev - 1.4.0dev + 1.5.0dev + 1.5.0dev beta diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index 72a4c4cf94..e4f5cb8422 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -37,5 +37,5 @@ #include namespace grpc { -grpc::string Version() { return "1.4.0-dev"; } +grpc::string Version() { return "1.5.0-dev"; } } diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 8388bfd9cc..81156452f3 100755 --- a/src/csharp/Grpc.Core/Version.csproj.include +++ b/src/csharp/Grpc.Core/Version.csproj.include @@ -1,7 +1,7 @@ - 1.4.0-dev + 1.5.0-dev 3.3.0 diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index 2e55d9d80e..d507878c2d 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -48,11 +48,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "1.4.0.0"; + public const string CurrentAssemblyFileVersion = "1.5.0.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "1.4.0-dev"; + public const string CurrentVersion = "1.5.0-dev"; } } diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index aa8a8d3b17..35664cc762 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -28,7 +28,7 @@ @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @rem Current package versions -set VERSION=1.4.0-dev +set VERSION=1.5.0-dev @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh index d33923845c..7dc07a220d 100755 --- a/src/csharp/build_packages_dotnetcli.sh +++ b/src/csharp/build_packages_dotnetcli.sh @@ -54,7 +54,7 @@ dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts -nuget pack Grpc.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts -nuget pack Grpc.Tools.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts +nuget pack Grpc.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts +nuget pack Grpc.Tools.nuspec -Version "1.5.0-dev" -OutputDirectory ../../artifacts (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg) diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json index 37c9b7a54f..0922f54a39 100644 --- a/src/node/health_check/package.json +++ b/src/node/health_check/package.json @@ -1,6 +1,6 @@ { "name": "grpc-health-check", - "version": "1.4.0-dev", + "version": "1.5.0-dev", "author": "Google Inc.", "description": "Health check service for use with gRPC", "repository": { @@ -15,7 +15,7 @@ } ], "dependencies": { - "grpc": "^1.4.0-dev", + "grpc": "^1.5.0-dev", "lodash": "^3.9.3", "google-protobuf": "^3.0.0" }, diff --git a/src/node/tools/package.json b/src/node/tools/package.json index a81aa87f4b..542d52d48b 100644 --- a/src/node/tools/package.json +++ b/src/node/tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "1.4.0-dev", + "version": "1.5.0-dev", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "http://www.grpc.io/", diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 2f29058b59..711814e7fa 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.4.0-dev' + v = '1.5.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index c846f4214c..cacbce4644 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -38,4 +38,4 @@ // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.4.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.5.0-dev" diff --git a/src/php/composer.json b/src/php/composer.json index a4fba7e4f6..3a97e5fb41 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "BSD-3-Clause", - "version": "1.4.0", + "version": "1.5.0", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.3.0" diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h index 993ef2de27..303a63ec36 100644 --- a/src/php/ext/grpc/version.h +++ b/src/php/ext/grpc/version.h @@ -35,6 +35,6 @@ #ifndef VERSION_H #define VERSION_H -#define PHP_GRPC_VERSION "1.4.0" +#define PHP_GRPC_VERSION "1.5.0" #endif /* VERSION_H */ diff --git a/src/python/grpcio/grpc/_grpcio_metadata.py b/src/python/grpcio/grpc/_grpcio_metadata.py index a0cb0dd067..3ae2602d20 100644 --- a/src/python/grpcio/grpc/_grpcio_metadata.py +++ b/src/python/grpcio/grpc/_grpcio_metadata.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!! -__version__ = """1.4.0.dev0""" +__version__ = """1.5.0.dev0""" diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index ea4bc7ba20..f5bd29ff85 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION='1.4.0.dev0' +VERSION='1.5.0.dev0' diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index 26aa555e14..26a8301883 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION='1.4.0.dev0' +VERSION='1.5.0.dev0' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index 978d6b4011..f16737df80 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION='1.4.0.dev0' +VERSION='1.5.0.dev0' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index 5f0b084884..28cf8a8a62 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION='1.4.0.dev0' +VERSION='1.5.0.dev0' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index f30dff335f..e2e784d19f 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.4.0.dev' + VERSION = '1.5.0.dev' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 1f8d4afb95..4f74238df7 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -29,6 +29,6 @@ module GRPC module Tools - VERSION = '1.4.0.dev' + VERSION = '1.5.0.dev' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index 1f2aa81c85..417722a4d2 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION='1.4.0.dev0' +VERSION='1.5.0.dev0' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 3861bdb85a..23746de1aa 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.4.0-dev +PROJECT_NUMBER = 1.5.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 5bab66c7d6..52e722f56c 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.4.0-dev +PROJECT_NUMBER = 1.5.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a -- cgit v1.2.3 From a9f94e9882e5c9978fb6376d94a7144f53ab1c4b Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Tue, 30 May 2017 15:21:46 -0700 Subject: s/inline/__inline/ --- test/core/census/intrusive_hash_map_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/core/census/intrusive_hash_map_test.c b/test/core/census/intrusive_hash_map_test.c index fe8d3a1675..552546f9a3 100644 --- a/test/core/census/intrusive_hash_map_test.c +++ b/test/core/census/intrusive_hash_map_test.c @@ -49,7 +49,7 @@ static const uint32_t kInitialLog2Size = 4; typedef struct object { uint64_t val; } object; /* Helper function to allocate and initialize object. */ -static inline object *make_new_object(uint64_t val) { +static __inline object *make_new_object(uint64_t val) { object *obj = (object *)gpr_malloc(sizeof(object)); obj->val = val; return obj; @@ -63,7 +63,7 @@ typedef struct ptr_item { /* Helper function that creates a new hash map item. It is up to the user to * free the item that was allocated. */ -static inline ptr_item *make_ptr_item(uint64_t key, uint64_t value) { +static __inline ptr_item *make_ptr_item(uint64_t key, uint64_t value) { ptr_item *new_item = (ptr_item *)gpr_malloc(sizeof(ptr_item)); new_item->IHM_key = key; new_item->IHM_hash_link = NULL; -- cgit v1.2.3 From 7ed4a63512ca58ee608ed3f7fd6c2a6bbd1c2ffc Mon Sep 17 00:00:00 2001 From: Mak Dharma Date: Tue, 30 May 2017 20:04:36 -0700 Subject: clang-format --- src/core/ext/census/intrusive_hash_map.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/ext/census/intrusive_hash_map.c b/src/core/ext/census/intrusive_hash_map.c index d147f23364..9f56b765e1 100644 --- a/src/core/ext/census/intrusive_hash_map.c +++ b/src/core/ext/census/intrusive_hash_map.c @@ -46,7 +46,7 @@ static const size_t VECTOR_CHUNK_SIZE = (1 << 20) / sizeof(void *); /* Helper functions which return buckets from the chunked vector. */ static __inline void **get_mutable_bucket(const chunked_vector *buckets, - uint32_t index) { + uint32_t index) { if (index < VECTOR_CHUNK_SIZE) { return &buckets->first_[index]; } @@ -54,7 +54,8 @@ static __inline void **get_mutable_bucket(const chunked_vector *buckets, return &buckets->rest_[rest_index][index % VECTOR_CHUNK_SIZE]; } -static __inline void *get_bucket(const chunked_vector *buckets, uint32_t index) { +static __inline void *get_bucket(const chunked_vector *buckets, + uint32_t index) { if (index < VECTOR_CHUNK_SIZE) { return buckets->first_[index]; } @@ -223,8 +224,8 @@ hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key) { * already existed. */ static __inline bool intrusive_hash_map_internal_insert(chunked_vector *buckets, - uint32_t hash_mask, - hm_item *item) { + uint32_t hash_mask, + hm_item *item) { const uint64_t key = item->key; uint32_t index = chunked_vector_hasher(key) & hash_mask; hm_item **slot = (hm_item **)get_mutable_bucket(buckets, index); -- cgit v1.2.3