From 7d21c04b2c9d9405bbd85c5a7ba0ece0cbae8b7a Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Tue, 10 Nov 2015 13:15:36 -0800 Subject: [PATCH] Fixes a multithreading bug in the ruby rpc_server This fixes the current ruby server interop test flakiness. - The interop tests recently changed so that clients access servers in parallel, meaning that the interop servers handle multiple rpcs at once, which is how this bug became visible - since this change, tests run against the ruby interop server have failed sporadically - the problem was that the block in #loop_handle_server_calls that is passed to the thread pool referenced a var in an enclosing block, which resulted in requests being processed by the wrong handler - this fix ensures that the block to be run on the thread pool thread does not have any references to vars in the enclosing block --- src/ruby/lib/grpc/generic/rpc_server.rb | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 228c500672b..0e318bd53b8 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -418,11 +418,11 @@ module GRPC an_rpc = @server.request_call(@cq, loop_tag, INFINITE_FUTURE) break if (!an_rpc.nil?) && an_rpc.call.nil? - c = new_active_server_call(an_rpc) - unless c.nil? - mth = an_rpc.method.to_sym - @pool.schedule(c) do |call| - rpc_descs[mth].run_server_method(call, rpc_handlers[mth]) + active_call = new_active_server_call(an_rpc) + unless active_call.nil? + @pool.schedule(active_call) do |ac| + c, mth = ac + rpc_descs[mth].run_server_method(c, rpc_handlers[mth]) end end rescue Core::CallError, RuntimeError => e @@ -442,6 +442,7 @@ module GRPC # allow the metadata to be accessed from the call handle_call_tag = Object.new an_rpc.call.metadata = an_rpc.metadata # attaches md to call for handlers + GRPC.logger.debug("call md is #{an_rpc.metadata}") connect_md = nil unless @connect_md_proc.nil? connect_md = @connect_md_proc.call(an_rpc.method, an_rpc.metadata) @@ -454,9 +455,11 @@ module GRPC # Create the ActiveCall GRPC.logger.info("deadline is #{an_rpc.deadline}; (now=#{Time.now})") rpc_desc = rpc_descs[an_rpc.method.to_sym] - ActiveCall.new(an_rpc.call, @cq, - rpc_desc.marshal_proc, rpc_desc.unmarshal_proc(:input), - an_rpc.deadline) + c = ActiveCall.new(an_rpc.call, @cq, + rpc_desc.marshal_proc, rpc_desc.unmarshal_proc(:input), + an_rpc.deadline) + mth = an_rpc.method.to_sym + [c, mth] end protected