Forum: Ruby-core [ruby-trunk - Bug #8125][Open] lost-tuple bug and fix for Rinda::TupleSpaceProxy.take

Posted by Joel Vanderwerf (vjoel)
on 2013-03-19 18:22
(Received via mailing list)
Issue #8125 has been reported by vjoel (Joel VanderWerf).

----------------------------------------
Bug #8125: lost-tuple bug and fix for Rinda::TupleSpaceProxy.take
https://bugs.ruby-lang.org/issues/8125

Author: vjoel (Joel VanderWerf)
Status: Open
Priority: Normal
Assignee:
Category: lib
Target version:
ruby -v: ruby 2.0.0p0 (2013-02-24) [x86_64-linux]


=begin

Rinda::TupleSpaceProxy prevents tuple loss during #take by exposing a 
"port" object on the client that the remote side (the tuplespace server) 
pushes to, instead of relying on the method return value. Pushing to the 
port fails if the process that called #take has exited, so the tuple 
will not be deleted from the tuplespace server.

However, if the process has not exited, and the thread that called #take 
was interrupted, the port still exists and accepts push requests (in the 
main drb thread). In this case the tuple is deleted on the server and 
not available on the client.

This is frequently a problem when using irb and manually interrupting 
take calls. It would also be a problem when using timeouts.

A concise reproduction of the problem is in the attached thread-int.rb.

The bug can be fixed by the patch below, which replaces the port array 
with a custom object that rejects pushes if the call stack has been 
unwound.

Note that this patch combines naturally with the faster take patch in 
#8119.


  diff --git a/lib/rinda/rinda.rb b/lib/rinda/rinda.rb
  index 18e284a..057c61a 100644
  --- a/lib/rinda/rinda.rb
  +++ b/lib/rinda/rinda.rb
  @@ -206,6 +206,23 @@ module Rinda
     # TupleSpaceProxy allows a remote Tuplespace to appear as local.

     class TupleSpaceProxy
  +    class Port
  +      attr_reader :val
  +
  +      def initialize
  +        @open = true
  +      end
  +
  +      def close
  +        @open = false
  +      end
  +
  +      def push val
  +        raise unless @open
  +        @val = val
  +        nil # so that val doesn't get marshalled again
  +      end
  +    end

       ##
       # Creates a new TupleSpaceProxy to wrap +ts+.
  @@ -222,6 +239,19 @@ module Rinda
       end

       ##
  +    # Safely takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.
  +    # Ensures that an interrupted thread will not become a lasting 
cause
  +    # of further data loss.
  +
  +    def take_safely(tuple, sec=nil, &block)
  +      port = Port.new
  +      @ts.move(DRbObject.new(port), tuple, sec, &block)
  +      port.val
  +    ensure
  +      port.close # don't let the DRb thread push to it when remote 
sends tuple
  +    end
  +
  +    ##
       # Takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.

       def take(tuple, sec=nil, &block)

=end
Posted by hsbt (Hiroshi SHIBATA) (Guest)
on 2013-03-19 23:50
(Received via mailing list)
Issue #8125 has been updated by hsbt (Hiroshi SHIBATA).

Assignee set to seki (Masatoshi Seki)


----------------------------------------
Bug #8125: lost-tuple bug and fix for Rinda::TupleSpaceProxy.take
https://bugs.ruby-lang.org/issues/8125#change-37744

Author: vjoel (Joel VanderWerf)
Status: Open
Priority: Normal
Assignee: seki (Masatoshi Seki)
Category: lib
Target version:
ruby -v: ruby 2.0.0p0 (2013-02-24) [x86_64-linux]


=begin

Rinda::TupleSpaceProxy prevents tuple loss during #take by exposing a 
"port" object on the client that the remote side (the tuplespace server) 
pushes to, instead of relying on the method return value. Pushing to the 
port fails if the process that called #take has exited, so the tuple 
will not be deleted from the tuplespace server.

However, if the process has not exited, and the thread that called #take 
was interrupted, the port still exists and accepts push requests (in the 
main drb thread). In this case the tuple is deleted on the server and 
not available on the client.

This is frequently a problem when using irb and manually interrupting 
take calls. It would also be a problem when using timeouts.

A concise reproduction of the problem is in the attached thread-int.rb.

The bug can be fixed by the patch below, which replaces the port array 
with a custom object that rejects pushes if the call stack has been 
unwound.

Note that this patch combines naturally with the faster take patch in 
#8119.


  diff --git a/lib/rinda/rinda.rb b/lib/rinda/rinda.rb
  index 18e284a..057c61a 100644
  --- a/lib/rinda/rinda.rb
  +++ b/lib/rinda/rinda.rb
  @@ -206,6 +206,23 @@ module Rinda
     # TupleSpaceProxy allows a remote Tuplespace to appear as local.

     class TupleSpaceProxy
  +    class Port
  +      attr_reader :val
  +
  +      def initialize
  +        @open = true
  +      end
  +
  +      def close
  +        @open = false
  +      end
  +
  +      def push val
  +        raise unless @open
  +        @val = val
  +        nil # so that val doesn't get marshalled again
  +      end
  +    end

       ##
       # Creates a new TupleSpaceProxy to wrap +ts+.
  @@ -222,6 +239,19 @@ module Rinda
       end

       ##
  +    # Safely takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.
  +    # Ensures that an interrupted thread will not become a lasting 
cause
  +    # of further data loss.
  +
  +    def take_safely(tuple, sec=nil, &block)
  +      port = Port.new
  +      @ts.move(DRbObject.new(port), tuple, sec, &block)
  +      port.val
  +    ensure
  +      port.close # don't let the DRb thread push to it when remote 
sends tuple
  +    end
  +
  +    ##
       # Takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.

       def take(tuple, sec=nil, &block)

=end
Posted by drbrain (Eric Hodel) (Guest)
on 2013-03-23 08:23
(Received via mailing list)
Issue #8125 has been updated by drbrain (Eric Hodel).

File rinda.rb.8215.patch added
Status changed from Open to Assigned

I think the safe take should be the default take.

I updated your patch and converted thread-int.rb into a test.
----------------------------------------
Bug #8125: lost-tuple bug and fix for Rinda::TupleSpaceProxy.take
https://bugs.ruby-lang.org/issues/8125#change-37840

Author: vjoel (Joel VanderWerf)
Status: Assigned
Priority: Normal
Assignee: seki (Masatoshi Seki)
Category: lib
Target version:
ruby -v: ruby 2.0.0p0 (2013-02-24) [x86_64-linux]


=begin

Rinda::TupleSpaceProxy prevents tuple loss during #take by exposing a 
"port" object on the client that the remote side (the tuplespace server) 
pushes to, instead of relying on the method return value. Pushing to the 
port fails if the process that called #take has exited, so the tuple 
will not be deleted from the tuplespace server.

However, if the process has not exited, and the thread that called #take 
was interrupted, the port still exists and accepts push requests (in the 
main drb thread). In this case the tuple is deleted on the server and 
not available on the client.

This is frequently a problem when using irb and manually interrupting 
take calls. It would also be a problem when using timeouts.

A concise reproduction of the problem is in the attached thread-int.rb.

The bug can be fixed by the patch below, which replaces the port array 
with a custom object that rejects pushes if the call stack has been 
unwound.

Note that this patch combines naturally with the faster take patch in 
#8119.


  diff --git a/lib/rinda/rinda.rb b/lib/rinda/rinda.rb
  index 18e284a..057c61a 100644
  --- a/lib/rinda/rinda.rb
  +++ b/lib/rinda/rinda.rb
  @@ -206,6 +206,23 @@ module Rinda
     # TupleSpaceProxy allows a remote Tuplespace to appear as local.

     class TupleSpaceProxy
  +    class Port
  +      attr_reader :val
  +
  +      def initialize
  +        @open = true
  +      end
  +
  +      def close
  +        @open = false
  +      end
  +
  +      def push val
  +        raise unless @open
  +        @val = val
  +        nil # so that val doesn't get marshalled again
  +      end
  +    end

       ##
       # Creates a new TupleSpaceProxy to wrap +ts+.
  @@ -222,6 +239,19 @@ module Rinda
       end

       ##
  +    # Safely takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.
  +    # Ensures that an interrupted thread will not become a lasting 
cause
  +    # of further data loss.
  +
  +    def take_safely(tuple, sec=nil, &block)
  +      port = Port.new
  +      @ts.move(DRbObject.new(port), tuple, sec, &block)
  +      port.val
  +    ensure
  +      port.close # don't let the DRb thread push to it when remote 
sends tuple
  +    end
  +
  +    ##
       # Takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.

       def take(tuple, sec=nil, &block)

=end
Posted by drbrain (Eric Hodel) (Guest)
on 2013-03-23 08:26
(Received via mailing list)
Issue #8125 has been updated by drbrain (Eric Hodel).

File rinda.rb.8215.2.patch added

Here is an updated patch that matches the rinda style and removes a 
leftover p
----------------------------------------
Bug #8125: lost-tuple bug and fix for Rinda::TupleSpaceProxy.take
https://bugs.ruby-lang.org/issues/8125#change-37841

Author: vjoel (Joel VanderWerf)
Status: Assigned
Priority: Normal
Assignee: seki (Masatoshi Seki)
Category: lib
Target version:
ruby -v: ruby 2.0.0p0 (2013-02-24) [x86_64-linux]


=begin

Rinda::TupleSpaceProxy prevents tuple loss during #take by exposing a 
"port" object on the client that the remote side (the tuplespace server) 
pushes to, instead of relying on the method return value. Pushing to the 
port fails if the process that called #take has exited, so the tuple 
will not be deleted from the tuplespace server.

However, if the process has not exited, and the thread that called #take 
was interrupted, the port still exists and accepts push requests (in the 
main drb thread). In this case the tuple is deleted on the server and 
not available on the client.

This is frequently a problem when using irb and manually interrupting 
take calls. It would also be a problem when using timeouts.

A concise reproduction of the problem is in the attached thread-int.rb.

The bug can be fixed by the patch below, which replaces the port array 
with a custom object that rejects pushes if the call stack has been 
unwound.

Note that this patch combines naturally with the faster take patch in 
#8119.


  diff --git a/lib/rinda/rinda.rb b/lib/rinda/rinda.rb
  index 18e284a..057c61a 100644
  --- a/lib/rinda/rinda.rb
  +++ b/lib/rinda/rinda.rb
  @@ -206,6 +206,23 @@ module Rinda
     # TupleSpaceProxy allows a remote Tuplespace to appear as local.

     class TupleSpaceProxy
  +    class Port
  +      attr_reader :val
  +
  +      def initialize
  +        @open = true
  +      end
  +
  +      def close
  +        @open = false
  +      end
  +
  +      def push val
  +        raise unless @open
  +        @val = val
  +        nil # so that val doesn't get marshalled again
  +      end
  +    end

       ##
       # Creates a new TupleSpaceProxy to wrap +ts+.
  @@ -222,6 +239,19 @@ module Rinda
       end

       ##
  +    # Safely takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.
  +    # Ensures that an interrupted thread will not become a lasting 
cause
  +    # of further data loss.
  +
  +    def take_safely(tuple, sec=nil, &block)
  +      port = Port.new
  +      @ts.move(DRbObject.new(port), tuple, sec, &block)
  +      port.val
  +    ensure
  +      port.close # don't let the DRb thread push to it when remote 
sends tuple
  +    end
  +
  +    ##
       # Takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.

       def take(tuple, sec=nil, &block)

=end
Posted by drbrain (Eric Hodel) (Guest)
on 2013-03-23 08:39
(Received via mailing list)
Issue #8125 has been updated by drbrain (Eric Hodel).

File rinda.rb.8215.3.patch added

Oops, I forgot to run all the tests, this fixes the remaining tests by 
restoring an accidentally deleted line.
----------------------------------------
Bug #8125: lost-tuple bug and fix for Rinda::TupleSpaceProxy.take
https://bugs.ruby-lang.org/issues/8125#change-37842

Author: vjoel (Joel VanderWerf)
Status: Assigned
Priority: Normal
Assignee: seki (Masatoshi Seki)
Category: lib
Target version:
ruby -v: ruby 2.0.0p0 (2013-02-24) [x86_64-linux]


=begin

Rinda::TupleSpaceProxy prevents tuple loss during #take by exposing a 
"port" object on the client that the remote side (the tuplespace server) 
pushes to, instead of relying on the method return value. Pushing to the 
port fails if the process that called #take has exited, so the tuple 
will not be deleted from the tuplespace server.

However, if the process has not exited, and the thread that called #take 
was interrupted, the port still exists and accepts push requests (in the 
main drb thread). In this case the tuple is deleted on the server and 
not available on the client.

This is frequently a problem when using irb and manually interrupting 
take calls. It would also be a problem when using timeouts.

A concise reproduction of the problem is in the attached thread-int.rb.

The bug can be fixed by the patch below, which replaces the port array 
with a custom object that rejects pushes if the call stack has been 
unwound.

Note that this patch combines naturally with the faster take patch in 
#8119.


  diff --git a/lib/rinda/rinda.rb b/lib/rinda/rinda.rb
  index 18e284a..057c61a 100644
  --- a/lib/rinda/rinda.rb
  +++ b/lib/rinda/rinda.rb
  @@ -206,6 +206,23 @@ module Rinda
     # TupleSpaceProxy allows a remote Tuplespace to appear as local.

     class TupleSpaceProxy
  +    class Port
  +      attr_reader :val
  +
  +      def initialize
  +        @open = true
  +      end
  +
  +      def close
  +        @open = false
  +      end
  +
  +      def push val
  +        raise unless @open
  +        @val = val
  +        nil # so that val doesn't get marshalled again
  +      end
  +    end

       ##
       # Creates a new TupleSpaceProxy to wrap +ts+.
  @@ -222,6 +239,19 @@ module Rinda
       end

       ##
  +    # Safely takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.
  +    # Ensures that an interrupted thread will not become a lasting 
cause
  +    # of further data loss.
  +
  +    def take_safely(tuple, sec=nil, &block)
  +      port = Port.new
  +      @ts.move(DRbObject.new(port), tuple, sec, &block)
  +      port.val
  +    ensure
  +      port.close # don't let the DRb thread push to it when remote 
sends tuple
  +    end
  +
  +    ##
       # Takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.

       def take(tuple, sec=nil, &block)

=end
Posted by seki (Masatoshi Seki) (Guest)
on 2013-03-23 11:17
(Received via mailing list)
Issue #8125 has been updated by seki (Masatoshi Seki).

Assignee changed from seki (Masatoshi Seki) to drbrain (Eric Hodel)

please commit it!
----------------------------------------
Bug #8125: lost-tuple bug and fix for Rinda::TupleSpaceProxy.take
https://bugs.ruby-lang.org/issues/8125#change-37849

Author: vjoel (Joel VanderWerf)
Status: Assigned
Priority: Normal
Assignee: drbrain (Eric Hodel)
Category: lib
Target version:
ruby -v: ruby 2.0.0p0 (2013-02-24) [x86_64-linux]


=begin

Rinda::TupleSpaceProxy prevents tuple loss during #take by exposing a 
"port" object on the client that the remote side (the tuplespace server) 
pushes to, instead of relying on the method return value. Pushing to the 
port fails if the process that called #take has exited, so the tuple 
will not be deleted from the tuplespace server.

However, if the process has not exited, and the thread that called #take 
was interrupted, the port still exists and accepts push requests (in the 
main drb thread). In this case the tuple is deleted on the server and 
not available on the client.

This is frequently a problem when using irb and manually interrupting 
take calls. It would also be a problem when using timeouts.

A concise reproduction of the problem is in the attached thread-int.rb.

The bug can be fixed by the patch below, which replaces the port array 
with a custom object that rejects pushes if the call stack has been 
unwound.

Note that this patch combines naturally with the faster take patch in 
#8119.


  diff --git a/lib/rinda/rinda.rb b/lib/rinda/rinda.rb
  index 18e284a..057c61a 100644
  --- a/lib/rinda/rinda.rb
  +++ b/lib/rinda/rinda.rb
  @@ -206,6 +206,23 @@ module Rinda
     # TupleSpaceProxy allows a remote Tuplespace to appear as local.

     class TupleSpaceProxy
  +    class Port
  +      attr_reader :val
  +
  +      def initialize
  +        @open = true
  +      end
  +
  +      def close
  +        @open = false
  +      end
  +
  +      def push val
  +        raise unless @open
  +        @val = val
  +        nil # so that val doesn't get marshalled again
  +      end
  +    end

       ##
       # Creates a new TupleSpaceProxy to wrap +ts+.
  @@ -222,6 +239,19 @@ module Rinda
       end

       ##
  +    # Safely takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.
  +    # Ensures that an interrupted thread will not become a lasting 
cause
  +    # of further data loss.
  +
  +    def take_safely(tuple, sec=nil, &block)
  +      port = Port.new
  +      @ts.move(DRbObject.new(port), tuple, sec, &block)
  +      port.val
  +    ensure
  +      port.close # don't let the DRb thread push to it when remote 
sends tuple
  +    end
  +
  +    ##
       # Takes +tuple+ from the proxied TupleSpace.  See 
TupleSpace#take.

       def take(tuple, sec=nil, &block)

=end
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.