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