rinda.rb.8215.patch

Eric Hodel, 03/23/2013 04:21 PM

Download (2.84 KB)

View differences:

lib/rinda/rinda.rb (working copy)
206 206
  # TupleSpaceProxy allows a remote Tuplespace to appear as local.
207 207

  
208 208
  class TupleSpaceProxy
209
    ##
210
    # A Port ensures that a moved tuple arrives properly at its destination
211
    # and does not get lost.
212
    #
213
    # See https://bugs.ruby-lang.org/issues/8125
214

  
215
    class Port # :nodoc:
216
      attr_reader :value
217

  
218
      def self.deliver
219
        port = new
220

  
221
        begin
222
          yield port
223
        ensure
224
          port.close
225
        end
226

  
227
        port.value
228
      end
229

  
230
      def initialize
231
        @open = true
232
        @value = nil
233
      end
234

  
235
      ##
236
      # Don't let the DRb thread push to it when remote sends tuple
237

  
238
      def close
239
        @open = false
240
      end
241

  
242
      ##
243
      # Stores +value+ and ensure it does not get marshaled multiple times.
244

  
245
      def push value
246
        raise 'port closed' unless @open
247

  
248
        @value = value
249

  
250
        nil # avoid Marshal
251
      end
252
    end
209 253

  
210 254
    ##
211 255
    # Creates a new TupleSpaceProxy to wrap +ts+.
......
225 269
    # Takes +tuple+ from the proxied TupleSpace.  See TupleSpace#take.
226 270

  
227 271
    def take(tuple, sec=nil, &block)
228
      port = []
229
      @ts.move(DRbObject.new(port), tuple, sec, &block)
230
      port[0]
272
      Port.deliver do |port|
273
        @ts.move(DRbObject.new(port), tuple, sec, &block)
274
      end
231 275
    end
232 276

  
233 277
    ##
test/rinda/test_rinda.rb (working copy)
477 477
                 @ts.take({'head' => 1, 'tail' => 2}, 0))
478 478
  end
479 479

  
480
  @server = DRb.primary_server || DRb.start_service
480
  def test_take_bug_8215
481
    service = DRb.start_service(nil, @ts_base)
482

  
483
    uri = service.uri
484

  
485
    c1 = fork do
486
      DRb.start_service
487
      ro = DRbObject.new_with_uri(uri)
488
      ts = Rinda::TupleSpaceProxy.new(ro)
489
      th = Thread.new do
490
        p :waiting
491
        ts.take([:test_take, nil])
492
      end
493
      Kernel.sleep 0.1
494
      th.raise Interrupt # causes loss of the taken tuple
495
      ts.write([:barrier, :continue])
496
      Kernel.sleep
497
    end
498

  
499
    @ts_base.take([:barrier, :continue])
500

  
501
    c2 = fork do
502
      DRb.start_service
503
      ro = DRbObject.new_with_uri(uri)
504
      ts = Rinda::TupleSpaceProxy.new(ro)
505
      ts.write([:test_take, 42])
506
    end
507

  
508
    status = Process.wait c2
509

  
510
    assert_equal [[:test_take, 42]], @ts_base.read_all([:test_take, nil]),
511
                 '[bug:8215] tuple lost'
512
  ensure
513
    Process.kill "TERM", c2 if c2 && status.nil?
514
    Process.kill "TERM", c1 if c1
515
    service.stop_service
516
  end
481 517
end
482 518

  
483 519
end