Bug #6416

Deadlock when calling Thread#join from signal interrupt context

Added by Timothy Elliott almost 2 years ago. Updated over 1 year ago.

[ruby-core:44956]
Status:Closed
Priority:Normal
Assignee:Motohiro KOSAKI
Category:-
Target version:2.0.0
ruby -v:ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux] Backport:

Description

=begin
The interpreter can deadlock when calling Thread#join both from the main context and from the signal handler context.

t = Thread.new{ sleep 3 }

Signal.trap "SIGINT" do
t.join
end

puts 'Press ctrl + c now'
t.join

The above will deadlock on linux x86_64 with ruby 1.9.x and ruby trunk. It works fine with ruby 1.8.7-p352 and JRuby.

=end

Associated revisions

Revision 37852
Added by Motohiro KOSAKI over 1 year ago

  • vmcore.h (rbthreadstruct): added 'intrap' member for marking running trap handler.
  • signal.c (signalexec): turn on intrap when running trap.
  • thread.c (InitThread, threadcreatecore): initialize intrap when creating new threads.
  • thread.c (threadjoinm): raise ThreadError when running trap handler.Bug [#6416]
  • test/ruby/testthread.rb (testthreadjoinin_trap): new test for the above.

History

#1 Updated by Yusuke Endoh almost 2 years ago

  • Status changed from Open to Assigned
  • Assignee set to Motohiro KOSAKI

Kosaki-san, could you take a look?

Yusuke Endoh mame@tsg.ne.jp

#2 Updated by Motohiro KOSAKI almost 2 years ago

  • Assignee changed from Motohiro KOSAKI to Koichi Sasada

Hi ko1,

This is because threadjoin() is not designed reentrant. It can insert a thread twice joinlist. And then, join_list
is going to become circular ring and it lead to deadlock.

So, I think th.join in trap context should raise ThreadError. What do you think?

#3 Updated by Koichi Sasada over 1 year ago

  • Target version set to 2.0.0

Please give me a time.

#4 Updated by Koichi Sasada over 1 year ago

  • Assignee changed from Koichi Sasada to Motohiro KOSAKI

I agree with kosaki-san's comment.

#5 Updated by Motohiro KOSAKI over 1 year ago

  • Status changed from Assigned to Closed

Fixed at r37852.
Thanks, Timothy!

#6 Updated by Narihiro Nakamura over 1 year ago

Hello

I need sometimes to call Thread#join in Signal.trap when I want to implement safe termination in a server.
For instance: https://gist.github.com/4158509

Is it a wrong use case in the first place?

Thanks.

#7 Updated by Motohiro KOSAKI over 1 year ago

Nari,

In your case, main thread and trap handler uses the same mutex and it is racy and deadlockable. Even if I revert my change, it wouldn't work.

#8 Updated by Narihiro Nakamura over 1 year ago

kosaki (Motohiro KOSAKI) wrote:

Nari,

In your case, main thread and trap handler uses the same mutex and it is racy and deadlockable. Even if I revert my change, it wouldn't work.

I see, Thanks!

Also available in: Atom PDF