Threads and Deadlocks


#1

It seems that the standard ruby interpreter is able to detect deadlocks
(at least it detects when all threads are deadlocked).

In this case it terminates. It appears it doesn’t do throwing an
exception…

Where can I find more infos about this? Can I insert into this and break
the deadlock in a (hopefully) softer way (I could know a specific thread
can be terminated).

Where can I find some infos about the deadlock revelation algorithms it
uses and such? This is just part of the “default” ruby interpreter or it
is defined in ruby itself?

Moreover how are regarded threads in the Ruby community? When I use
Python it’s usually not advised and it is encouraged to move to an
asynchronous model (Twisted).

Thanks in advance.


#2

On Mar 11, 2006, at 8:53 AM, Mc Osten wrote:

It seems that the standard ruby interpreter is able to detect
deadlocks (at least it detects when all threads are deadlocked).

In this case it terminates. It appears it doesn’t do throwing an
exception…

There’s nowhere to throw an exception to, all threads are blocked
from running.

Where can I find more infos about this? Can I insert into this and
break the deadlock in a (hopefully) softer way (I could know a
specific thread can be terminated).

No. The error is in your programming. Terminating a thread won’t
break the deadlock because either it is holding a resource other
threads are waiting on or it is waiting on a resource some other
thread is using and sleeping.

Where can I find some infos about the deadlock revelation
algorithms it uses and such? This is just part of the “default”
ruby interpreter or it is defined in ruby itself?

It is part of the interpreter and written in C.

Moreover how are regarded threads in the Ruby community? When I use
Python it’s usually not advised and it is encouraged to move to an
asynchronous model (Twisted).

Everybody uses threads in Ruby.


Eric H. - removed_email_address@domain.invalid - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com


#3

Eric H. ha scritto:

There’s nowhere to throw an exception to, all threads are blocked from
running.

What happens then? Is there any documentation about this (I’d rather not
to read directly the source, but if there is no other way…)

No. The error is in your programming. Terminating a thread won’t break
the deadlock because either it is holding a resource other threads are
waiting on or it is waiting on a resource some other thread is using and
sleeping.

No. The error is not in my programming since this is no real case.

The deadlock is intentionally created in the most obvious way just to
see what happened; in this sense the program is correct, it does exaclty
what it was meant to: it deadlocks.

If I can somehow trap the event that makes the ruby interpreter
terminate I could obviously recover the deadlock, since blocked
resources would have been constructed to be recoverable.

Probably I am not able to explain what I’m looking for: this is not real
case programming. This are kind of teaching examples.

It is part of the interpreter and written in C.

So I can’t assume JRuby (for example) will act the same, can I?

Everybody uses threads in Ruby.

Ok.


#4

On Sat, 11 Mar 2006 18:53:29 +0100, Robert K. wrote:

I did some experimenting with the attached script.

Thank you very much.

The trace actually seems
to show a “raise” but none of the exception blocks catches anything.

Yes. I tried to with a generic rescue clause and it did not catch.

“ensure” is executed nevertheless. This is strange. Another strange thing
is that “raise” does not show up if you uncomment those two lines that print
the thread ids.

I have no clues about it…

For these low level things you should not rely on similar behavior.

Ok. In fact I’m not suprised.


#5

Mc Osten removed_email_address@domain.invalid wrote:

Eric H. ha scritto:

There’s nowhere to throw an exception to, all threads are blocked
from running.

What happens then? Is there any documentation about this (I’d rather
not to read directly the source, but if there is no other way…)

I did some experimenting with the attached script. The trace actually
seems
to show a “raise” but none of the exception blocks catches anything.
“ensure” is executed nevertheless. This is strange. Another strange
thing
is that “raise” does not show up if you uncomment those two lines that
print
the thread ids.

If I can somehow trap the event that makes the ruby interpreter
terminate I could obviously recover the deadlock, since blocked
resources would have been constructed to be recoverable.

It is generally the better approach to avoid deadlocks programmatically.

Probably I am not able to explain what I’m looking for: this is not
real case programming. This are kind of teaching examples.

It is part of the interpreter and written in C.

So I can’t assume JRuby (for example) will act the same, can I?

For these low level things you should not rely on similar behavior. And
you
also should not rely on deadlock detection. I guess the interpreter
uses
some kind of special mechanism. If you want to know what exactly
happens
here a look into the source code is probably the best.

Kind regards

robert

#6

Hi,

At Sat, 11 Mar 2006 23:53:43 +0900,
Mc Osten wrote in [ruby-talk:183655]:

It seems that the standard ruby interpreter is able to detect deadlocks
(at least it detects when all threads are deadlocked).

In this case it terminates. It appears it doesn’t do throwing an
exception…

ThreadError will be raised in the main thread.

$ ruby -e ‘begin Thread.start{Thread.main.join}.join; rescue
ThreadError => e; p e; end’
#<ThreadError: Thread#join: deadlock 0xb7df6824 - mutual
join(0xb7de9368)>


#7

removed_email_address@domain.invalid wrote:

ThreadError will be raised in the main thread.

$ ruby -e ‘begin Thread.start{Thread.main.join}.join; rescue
ThreadError => e; p e; end’ #<ThreadError: Thread#join: deadlock
0xb7df6824 - mutual join(0xb7de9368)>

Hm, but why then isn’t it caught by a clause “rescue Exception => e”?

Wondering…

robert

#8

On Mon, 13 Mar 2006 17:33:30 +0100, Robert K. wrote:

Hm, but why then isn’t it caught by a clause “rescue Exception => e”?

For example in this program, no exception is caught:

require “thread”

m1 = Mutex.new
m2 = Mutex.new

begin

p “begin”
t1 = Thread.new do
m1.lock;
sleep rand ;
begin
m2.lock
rescue ThreadError => e;
print “Rescuing t1”
end
end

t2 = Thread.new do
m2.lock;
sleep rand ;
begin
m1.lock
rescue ThreadError => e;
print “Rescuing t2”
end
end

p “joining…”
t1.join
t2.join

rescue ThreadError => e;
print “Rescuing…”
end


#9

JRuby currently uses Java threads to implement Ruby threads, and
therefore
the only deadlock detection available is that provided by Java. However,
if
you have threads deadlocking it is, as others have said, an issue with
your
code that should be corrected. Ruby makes an assumption that the threads
will never wake up (or perhaps knows they will never wake up because of
circular dependencies) and chooses to kill them. In Java, you’re
perfectly
welcome to create deadlocked threads and Java will allow you to deadlock
if
that’s how you choose to write your code. Either way, if you have
deadlocks,
you need to correct that in your code rather than expecting the
interpreter
to save you.