ruby-changes:58236
From: Jeremy <ko1@a...>
Date: Mon, 14 Oct 2019 14:20:50 +0900 (JST)
Subject: [ruby-changes:58236] d0ed935d5b (master): Fix some DRb issues (#2552)
https://git.ruby-lang.org/ruby.git/commit/?id=d0ed935d5b From d0ed935d5bf8c3fce9800742a36e44fb7f63dda4 Mon Sep 17 00:00:00 2001 From: Jeremy Evans <code@j...> Date: Sun, 13 Oct 2019 22:20:32 -0700 Subject: Fix some DRb issues (#2552) * Handle BasicObject in drb Also fix a bug in rescue clause of any_to_s because sprintf does not handle the %l modifier. Fixes [Bug #7833] * Do not send a reply to the client if there is a connection error This allows for normal TCP shutdown (fin-ack-fin-ack instead of fin-ack-push-rst). Patch from pierre@m... (Pierre-Alexandre Meyer). Fixes [Bug #2339] * Detect fork and do not reuse forked connections in drb This associates each DRbConn with a pid, and if the pid changes, it closes any DRbConns in the pool with a pid that no longer matches. This fixes DRb servers from sending messages intended for one client to another client after forking. Fixes [Bug #2718] Fixes [Bug #14471] diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb index caffd5d..8c2ef63 100644 --- a/lib/drb/drb.rb +++ b/lib/drb/drb.rb @@ -377,7 +377,12 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L377 # This implementation returns the object's __id__ in the local # object space. def to_id(obj) - obj.nil? ? nil : obj.__id__ + case obj + when Object + obj.nil? ? nil : obj.__id__ + when BasicObject + obj.__id__ + end end end @@ -560,7 +565,14 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L565 end def dump(obj, error=false) # :nodoc: - obj = make_proxy(obj, error) if obj.kind_of? DRbUndumped + case obj + when DRbUndumped + obj = make_proxy(obj, error) + when Object + # nothing + else + obj = make_proxy(obj, error) + end begin str = Marshal::dump(obj) rescue @@ -1092,7 +1104,14 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1104 def initialize(obj, uri=nil) @uri = nil @ref = nil - if obj.nil? + case obj + when Object + is_nil = obj.nil? + when BasicObject + is_nil = false + end + + if is_nil return if uri.nil? @uri, option = DRbProtocol.uri_option(uri, DRb.config) @ref = DRbURIOption.new(option) unless option.nil? @@ -1209,15 +1228,20 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1228 def self.open(remote_uri) # :nodoc: begin conn = nil + pid = $$ @mutex.synchronize do #FIXME new_pool = [] @pool.each do |c| - if conn.nil? and c.uri == remote_uri - conn = c if c.alive? + if c.pid == pid + if conn.nil? and c.uri == remote_uri + conn = c if c.alive? + else + new_pool.push c + end else - new_pool.push c + c.close end end @pool = new_pool @@ -1243,9 +1267,11 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1267 def initialize(remote_uri) # :nodoc: @uri = remote_uri + @pid = $$ @protocol = DRbProtocol.open(remote_uri, DRb.config) end attr_reader :uri # :nodoc: + attr_reader :pid # :nodoc: def send_message(ref, msg_id, arg, block) # :nodoc: @protocol.send_request(ref, msg_id, arg, block) @@ -1527,7 +1553,13 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1553 def any_to_s(obj) obj.to_s + ":#{obj.class}" rescue - sprintf("#<%s:0x%lx>", obj.class, obj.__id__) + case obj + when Object + klass = obj.class + else + klass = Kernel.instance_method(:class).bind(obj).call + end + sprintf("#<%s:0x%dx>", klass, obj.__id__) end # Check that a method is callable via dRuby. @@ -1543,14 +1575,27 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1575 raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id) - if obj.private_methods.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "private method `#{msg_id}' called for #{desc}" - elsif obj.protected_methods.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" + case obj + when Object + if obj.private_methods.include?(msg_id) + desc = any_to_s(obj) + raise NoMethodError, "private method `#{msg_id}' called for #{desc}" + elsif obj.protected_methods.include?(msg_id) + desc = any_to_s(obj) + raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" + else + true + end else - true + if Kernel.instance_method(:private_methods).bind(obj).call.include?(msg_id) + desc = any_to_s(obj) + raise NoMethodError, "private method `#{msg_id}' called for #{desc}" + elsif Kernel.instance_method(:protected_methods).bind(obj).call.include?(msg_id) + desc = any_to_s(obj) + raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" + else + true + end end end public :check_insecure_method @@ -1596,8 +1641,11 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1641 end end @succ = true - if @msg_id == :to_ary && @result.class == Array - @result = DRbArray.new(@result) + case @result + when Array + if @msg_id == :to_ary + @result = DRbArray.new(@result) + end end return @succ, @result rescue StandardError, ScriptError, Interrupt @@ -1678,7 +1726,9 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1726 invoke_method = InvokeMethod.new(self, client) succ, result = invoke_method.perform error_print(result) if !succ && verbose - client.send_reply(succ, result) + unless DRbConnError === result && result.message == 'connection closed' + client.send_reply(succ, result) + end rescue Exception => e error_print(e) if verbose ensure diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb index 9ac3e08..6b8cd5d 100644 --- a/test/drb/drbtest.rb +++ b/test/drb/drbtest.rb @@ -158,6 +158,14 @@ module DRbCore https://github.com/ruby/ruby/blob/trunk/test/drb/drbtest.rb#L158 end end + def test_02_basic_object + obj = @there.basic_object + assert_kind_of(DRb::DRbObject, obj) + assert_equal(1, obj.foo) + assert_raise(NoMethodError){obj.prot} + assert_raise(NoMethodError){obj.priv} + end + def test_02_unknown obj = @there.unknown_class assert_kind_of(DRb::DRbUnknown, obj) diff --git a/test/drb/ut_drb.rb b/test/drb/ut_drb.rb index 6a94a0f..b1306d0 100644 --- a/test/drb/ut_drb.rb +++ b/test/drb/ut_drb.rb @@ -63,6 +63,15 @@ class DRbEx https://github.com/ruby/ruby/blob/trunk/test/drb/ut_drb.rb#L63 FooBar.new end + class BO < ::BasicObject + def foo; 1 end + protected def prot; 2; end + private def priv; 3; end + end + def basic_object + BO.new + end + def unknown_class Unknown2.new end -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/