Weird deadlock problems with Slave/drb

#!/usr/bin/env ruby

# Original program idea:
# Write a ruby program that checks the integrity of all my FLAC music
files,
# and that makes use of my MacBooks Core Duo CPU. Since Ruby doesn't
support
# native threadds, I decided to use the Slave library.

···

#
# Problem:
# I start 3 Slave servers:
# worker1 and worker2 both query the filename server to get the next
filename
# to process.
#
# On Mac OS 10.4.10, ruby 1.8.6 (Locomotive or MacPorts, same problem)
the second
# worker server process never starts, it seems to sleep forver, and I
don't
# see my programming mistake.
#
# The same problem occurs on Ubuntu Feisty.
#
# However: IF you start the 2nd worker after the first worker completed
its
# work, it runs without problem.
#
# And: If you disable the call to the filename server, both workers run
# in parallel, too, without deadlocking.
#
# So the problem has something to do with both workers trying to access
the
# same filename server.
#
# Any ideas?

require 'slave'
require 'monitor'
require 'fastthread'

class FlacTestServer

  def processFiles(filenameServer)
    50.times do |i|
      #sleep(0.02)
      #Activate this:
      #puts("PID #{ Process.pid }: Iteration #{ i }")
      #and disable this and both workers will run without worker 2
sleeping forever.
      puts("#{ Process.pid }: #{ filenameServer.nextFilename() }")
    end
  end
end

class FilenameServer
  include MonitorMixin

  def initialize()
    super
    @counter = 0
  end

  def nextFilename()
    synchronize do
      # Return some dummy data
      @counter += 1
      "#{ Process.pid }, #{ @counter }"
    end
  end
end

if $0 == __FILE__

  fnServer = Slave.new() { FilenameServer.new() }.object

  worker1 = Slave.object({:async => true, :psname => 'Worker1'}) {
FlacTestServer.new().processFiles(fnServer) }

  # "Works" if you activate this:
  #worker1.join()

  worker2 = Slave.object({:async => true, :psname => 'Worker2'}) {
FlacTestServer.new().processFiles(fnServer) }

  # If you create the slaves using the following method instead, worker2
sometimes runs, sometimes not
  # and sometimes it runs only a few internal iterations before it
sleeps forever / deadlocks...?!?
  # But you can get it to work if you active the sleep call in line 37.
  #ftServer1 = Slave.new() { FlacTestServer.new() }.object()
  #ftServer2 = Slave.new() { FlacTestServer.new() }.object()
  #
  #worker1 = Thread.new() { ftServer1.processFiles(fnServer) }
  #worker2 = Thread.new() { ftServer2.processFiles(fnServer) }

  worker1.join()
  puts("Worker 1 terminated.")

  #puts("Worker 2 status: #{ worker2.status() }") until
worker2.join(0.15)
  worker2.join()
  puts("Worker 2 terminated.")

  puts("End main program: #{Process.pid}")
end

--
Posted via http://www.ruby-forum.com/.