rinda.rb.8215.3.patch

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

Download (2.91 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
  def test_take_bug_8215
481
    DRb.stop_service
482
    service = DRb.start_service(nil, @ts_base)
483

  
484
    uri = service.uri
485

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

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

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

  
510
    status = Process.wait(write)
511

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

  
480 520
  @server = DRb.primary_server || DRb.start_service
481 521
end
482 522