rinda.rb.8215.2.patch

Eric Hodel, 03/23/2013 04:26 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
    take = 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
        ts.take([:test_take, nil])
491
      end
492
      Kernel.sleep(0.1)
493
      th.raise(Interrupt) # causes loss of the taken tuple
494
      ts.write([:barrier, :continue])
495
      Kernel.sleep
496
    end
497

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

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

  
507
    status = Process.wait(take)
508

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

  
483 518
end