зеркало из https://github.com/github/ruby.git
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@mouraf.org (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]
This commit is contained in:
Родитель
95c420c4a6
Коммит
d0ed935d5b
|
@ -377,7 +377,12 @@ module DRb
|
||||||
# This implementation returns the object's __id__ in the local
|
# This implementation returns the object's __id__ in the local
|
||||||
# object space.
|
# object space.
|
||||||
def to_id(obj)
|
def to_id(obj)
|
||||||
|
case obj
|
||||||
|
when Object
|
||||||
obj.nil? ? nil : obj.__id__
|
obj.nil? ? nil : obj.__id__
|
||||||
|
when BasicObject
|
||||||
|
obj.__id__
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -560,7 +565,14 @@ module DRb
|
||||||
end
|
end
|
||||||
|
|
||||||
def dump(obj, error=false) # :nodoc:
|
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
|
begin
|
||||||
str = Marshal::dump(obj)
|
str = Marshal::dump(obj)
|
||||||
rescue
|
rescue
|
||||||
|
@ -1092,7 +1104,14 @@ module DRb
|
||||||
def initialize(obj, uri=nil)
|
def initialize(obj, uri=nil)
|
||||||
@uri = nil
|
@uri = nil
|
||||||
@ref = 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?
|
return if uri.nil?
|
||||||
@uri, option = DRbProtocol.uri_option(uri, DRb.config)
|
@uri, option = DRbProtocol.uri_option(uri, DRb.config)
|
||||||
@ref = DRbURIOption.new(option) unless option.nil?
|
@ref = DRbURIOption.new(option) unless option.nil?
|
||||||
|
@ -1209,16 +1228,21 @@ module DRb
|
||||||
def self.open(remote_uri) # :nodoc:
|
def self.open(remote_uri) # :nodoc:
|
||||||
begin
|
begin
|
||||||
conn = nil
|
conn = nil
|
||||||
|
pid = $$
|
||||||
|
|
||||||
@mutex.synchronize do
|
@mutex.synchronize do
|
||||||
#FIXME
|
#FIXME
|
||||||
new_pool = []
|
new_pool = []
|
||||||
@pool.each do |c|
|
@pool.each do |c|
|
||||||
|
if c.pid == pid
|
||||||
if conn.nil? and c.uri == remote_uri
|
if conn.nil? and c.uri == remote_uri
|
||||||
conn = c if c.alive?
|
conn = c if c.alive?
|
||||||
else
|
else
|
||||||
new_pool.push c
|
new_pool.push c
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
c.close
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@pool = new_pool
|
@pool = new_pool
|
||||||
end
|
end
|
||||||
|
@ -1243,9 +1267,11 @@ module DRb
|
||||||
|
|
||||||
def initialize(remote_uri) # :nodoc:
|
def initialize(remote_uri) # :nodoc:
|
||||||
@uri = remote_uri
|
@uri = remote_uri
|
||||||
|
@pid = $$
|
||||||
@protocol = DRbProtocol.open(remote_uri, DRb.config)
|
@protocol = DRbProtocol.open(remote_uri, DRb.config)
|
||||||
end
|
end
|
||||||
attr_reader :uri # :nodoc:
|
attr_reader :uri # :nodoc:
|
||||||
|
attr_reader :pid # :nodoc:
|
||||||
|
|
||||||
def send_message(ref, msg_id, arg, block) # :nodoc:
|
def send_message(ref, msg_id, arg, block) # :nodoc:
|
||||||
@protocol.send_request(ref, msg_id, arg, block)
|
@protocol.send_request(ref, msg_id, arg, block)
|
||||||
|
@ -1527,7 +1553,13 @@ module DRb
|
||||||
def any_to_s(obj)
|
def any_to_s(obj)
|
||||||
obj.to_s + ":#{obj.class}"
|
obj.to_s + ":#{obj.class}"
|
||||||
rescue
|
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
|
end
|
||||||
|
|
||||||
# Check that a method is callable via dRuby.
|
# Check that a method is callable via dRuby.
|
||||||
|
@ -1543,6 +1575,8 @@ module DRb
|
||||||
raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class
|
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)
|
raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id)
|
||||||
|
|
||||||
|
case obj
|
||||||
|
when Object
|
||||||
if obj.private_methods.include?(msg_id)
|
if obj.private_methods.include?(msg_id)
|
||||||
desc = any_to_s(obj)
|
desc = any_to_s(obj)
|
||||||
raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
|
raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
|
||||||
|
@ -1552,6 +1586,17 @@ module DRb
|
||||||
else
|
else
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
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
|
end
|
||||||
public :check_insecure_method
|
public :check_insecure_method
|
||||||
|
|
||||||
|
@ -1596,9 +1641,12 @@ module DRb
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@succ = true
|
@succ = true
|
||||||
if @msg_id == :to_ary && @result.class == Array
|
case @result
|
||||||
|
when Array
|
||||||
|
if @msg_id == :to_ary
|
||||||
@result = DRbArray.new(@result)
|
@result = DRbArray.new(@result)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
return @succ, @result
|
return @succ, @result
|
||||||
rescue StandardError, ScriptError, Interrupt
|
rescue StandardError, ScriptError, Interrupt
|
||||||
@result = $!
|
@result = $!
|
||||||
|
@ -1678,7 +1726,9 @@ module DRb
|
||||||
invoke_method = InvokeMethod.new(self, client)
|
invoke_method = InvokeMethod.new(self, client)
|
||||||
succ, result = invoke_method.perform
|
succ, result = invoke_method.perform
|
||||||
error_print(result) if !succ && verbose
|
error_print(result) if !succ && verbose
|
||||||
|
unless DRbConnError === result && result.message == 'connection closed'
|
||||||
client.send_reply(succ, result)
|
client.send_reply(succ, result)
|
||||||
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
error_print(e) if verbose
|
error_print(e) if verbose
|
||||||
ensure
|
ensure
|
||||||
|
|
|
@ -158,6 +158,14 @@ module DRbCore
|
||||||
end
|
end
|
||||||
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
|
def test_02_unknown
|
||||||
obj = @there.unknown_class
|
obj = @there.unknown_class
|
||||||
assert_kind_of(DRb::DRbUnknown, obj)
|
assert_kind_of(DRb::DRbUnknown, obj)
|
||||||
|
|
|
@ -63,6 +63,15 @@ class DRbEx
|
||||||
FooBar.new
|
FooBar.new
|
||||||
end
|
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
|
def unknown_class
|
||||||
Unknown2.new
|
Unknown2.new
|
||||||
end
|
end
|
||||||
|
|
Загрузка…
Ссылка в новой задаче