Manish
Manish

Reputation: 11

Ruby 192 recursive thread lock error

I am working with ruby 192 p290: under one unit-test script (shown below) throws ThreadError

1) Error:

test_orchpr_pass(TC_MyTest):

ThreadError: deadlock; recursive locking

internal:prelude:8:in `lock'

internal:prelude:8:in `synchronize'

testth.rb:121:in `orchpr_run'

testth.rb:158:in `test_orchpr_pass'

With ruby 187 gives error: Thread tried to join itself.

CODE

def orchpr_run(timeout = 60)


    # used by the update function to signal that a final update was
    # received from all clients

    @update_mutex.lock

    # required since we'll have to act as an observer to the DRb server
    DRb.start_service

    # get configuration objects
    run_config_type = DataLayer.get_run_config_type
    client_daemon = DataLayer.get_client_daemon_by_branch (run_config_type, @branch)
            client_daemon['port_no'] = 9096
            #get the servers for this client_daemon
    servers = DataLayer.get_servers(run_config_type, client_daemon.id)

    servers.each { |server| @pr[server.host_name] = OrchestratedPlatformRun.new(run_config_type, server, timeout) 

    }

    @pr.each_value { |x| x.add_observer(self) 

    @pr.each_value { |x| x.start(@service_command_pass, true) 


    # wait for update to receive notifications from all servers # this is the statement causing error:
    @update_mutex.synchronize {} end

Another piece of code throwing same error:

 require "thread"
 require "timeout"

 def calc_fib(n)
   if n == 0
     0
   elsif n == 1
     1
   else
     calc_fib(n-1) + calc_fib(n-2)
   end
 end

 lock = Mutex.new

 threads = 20.times.collect do
   Thread.new do
     20.times do
       begin
         Timeout.timeout(0.25) do
           lock.synchronize{ calc_fib(1000) }
         end
       rescue ThreadError => e
         puts "#{e.class}: #{e.message}:\n" + e.backtrace.join("\n") + "\n\n"
       rescue Timeout::Error => e
         #puts e.class
         nil
       end
     end
   end
 end

 threads.each{ |t| t.join }

Commenting synchronizing Block will cause the error to disappear but then then threads are not able to synchronize. I found some stuff on net, saying bug with ruby 192 , need changes in file prelude.rb and thread.c regarding MUTEX synchronization. But Under windows installation Unable to find file prelude.rb

Upvotes: 1

Views: 1253

Answers (1)

Frederick Cheung
Frederick Cheung

Reputation: 84132

If a mutex is locked by a thread then an error will be raised if you try and lock it again from the same thread

This is exactly what you are doing, since synchronize is just a convenience for method for locking the mutex, yielding to the block and then releasing the lock. I'm not sure what you're trying to do, but it feels to me like you might be trying to use mutexes for something other than their intended purposes.

Using threads and locks well is difficult to get right - you might want to look at celluloid for a different approach to concurrency.

Upvotes: 1

Related Questions