Forum: Ruby-core [ruby-trunk - Bug #6416][Open] Deadlock when calling Thread#join from signal interrupt context

Posted by Tim Elliott (ender672)
on 2012-05-08 23:15
(Received via mailing list)
Issue #6416 has been reported by ender672 (Timothy Elliott).

----------------------------------------
Bug #6416: Deadlock when calling Thread#join from signal interrupt 
context
https://bugs.ruby-lang.org/issues/6416

Author: ender672 (Timothy Elliott)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux]


=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
Posted by mame (Yusuke Endoh) (Guest)
on 2012-05-16 17:33
(Received via mailing list)
Issue #6416 has been updated by mame (Yusuke Endoh).

Status changed from Open to Assigned
Assignee set to kosaki (Motohiro KOSAKI)

Kosaki-san, could you take a look?

--
Yusuke Endoh <mame@tsg.ne.jp>
----------------------------------------
Bug #6416: Deadlock when calling Thread#join from signal interrupt 
context
https://bugs.ruby-lang.org/issues/6416#change-26662

Author: ender672 (Timothy Elliott)
Status: Assigned
Priority: Normal
Assignee: kosaki (Motohiro KOSAKI)
Category:
Target version:
ruby -v: ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux]


=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
Posted by kosaki (Motohiro KOSAKI) (Guest)
on 2012-05-18 10:05
(Received via mailing list)
Issue #6416 has been updated by kosaki (Motohiro KOSAKI).

Assignee changed from kosaki (Motohiro KOSAKI) to ko1 (Koichi Sasada)

Hi ko1,

This is because thread_join() is not designed reentrant. It can insert a 
thread twice join_list. 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?


----------------------------------------
Bug #6416: Deadlock when calling Thread#join from signal interrupt 
context
https://bugs.ruby-lang.org/issues/6416#change-26698

Author: ender672 (Timothy Elliott)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category:
Target version:
ruby -v: ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux]


=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
Posted by ko1 (Koichi Sasada) (Guest)
on 2012-10-30 01:22
(Received via mailing list)
Issue #6416 has been updated by ko1 (Koichi Sasada).

Target version set to 2.0.0

Please give me a time.
----------------------------------------
Bug #6416: Deadlock when calling Thread#join from signal interrupt 
context
https://bugs.ruby-lang.org/issues/6416#change-31957

Author: ender672 (Timothy Elliott)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category:
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux]


=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
Posted by ko1 (Koichi Sasada) (Guest)
on 2012-11-26 01:50
(Received via mailing list)
Issue #6416 has been updated by ko1 (Koichi Sasada).

Assignee changed from ko1 (Koichi Sasada) to kosaki (Motohiro KOSAKI)

I agree with kosaki-san's comment.

----------------------------------------
Bug #6416: Deadlock when calling Thread#join from signal interrupt 
context
https://bugs.ruby-lang.org/issues/6416#change-33920

Author: ender672 (Timothy Elliott)
Status: Assigned
Priority: Normal
Assignee: kosaki (Motohiro KOSAKI)
Category:
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux]


=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
Posted by kosaki (Motohiro KOSAKI) (Guest)
on 2012-11-26 12:02
(Received via mailing list)
Issue #6416 has been updated by kosaki (Motohiro KOSAKI).

Status changed from Assigned to Closed

Fixed at r37852.
Thanks, Timothy!
----------------------------------------
Bug #6416: Deadlock when calling Thread#join from signal interrupt 
context
https://bugs.ruby-lang.org/issues/6416#change-33951

Author: ender672 (Timothy Elliott)
Status: Closed
Priority: Normal
Assignee: kosaki (Motohiro KOSAKI)
Category:
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux]


=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
Posted by authorNari (Narihiro Nakamura) (Guest)
on 2012-11-28 03:31
(Received via mailing list)
Issue #6416 has been updated by authorNari (Narihiro Nakamura).


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.

----------------------------------------
Bug #6416: Deadlock when calling Thread#join from signal interrupt 
context
https://bugs.ruby-lang.org/issues/6416#change-34061

Author: ender672 (Timothy Elliott)
Status: Closed
Priority: Normal
Assignee: kosaki (Motohiro KOSAKI)
Category:
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux]


=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
Posted by kosaki (Motohiro KOSAKI) (Guest)
on 2012-11-28 03:47
(Received via mailing list)
Issue #6416 has been updated by kosaki (Motohiro KOSAKI).


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.
----------------------------------------
Bug #6416: Deadlock when calling Thread#join from signal interrupt 
context
https://bugs.ruby-lang.org/issues/6416#change-34062

Author: ender672 (Timothy Elliott)
Status: Closed
Priority: Normal
Assignee: kosaki (Motohiro KOSAKI)
Category:
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux]


=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
Posted by authorNari (Narihiro Nakamura) (Guest)
on 2012-11-28 05:02
(Received via mailing list)
Issue #6416 has been updated by authorNari (Narihiro Nakamura).


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!
----------------------------------------
Bug #6416: Deadlock when calling Thread#join from signal interrupt 
context
https://bugs.ruby-lang.org/issues/6416#change-34064

Author: ender672 (Timothy Elliott)
Status: Closed
Priority: Normal
Assignee: kosaki (Motohiro KOSAKI)
Category:
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-05-09 trunk 35598) [x86_64-linux]


=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
Posted by Joe L. (joe_l)
on 2013-01-01 02:21
I'm working on updating a gem to be compatible with Ruby 2.0 and am
currently using Ruby 2.0.0-preview2. I'm running into trouble with a
class which inherits from GServer and I think it's related to the change
discussed on this thread. Please look at the gist:
https://gist.github.com/4424479

Using Ruby <= 1.9.3, when sending an interrupt signal this code would
exit cleanly. Using Ruby 2.0, an exception is thrown on launcher.stop:

~/.rvm/rubies/ruby-2.0.0-preview2/lib/ruby/2.0.0/gserver.rb:116:in
`synchronize': can't be called from trap context (ThreadError)
    from
~/.rvm/rubies/ruby-2.0.0-preview2/lib/ruby/2.0.0/gserver.rb:116:in
`stop'

As you can see, I am not explicitly calling 'join' in the trap context
but 'synchronize' is called as part of GServer#close

gserver.rb
114   # Stop the server
115   def stop
116     @connectionsMutex.synchronize  {
117       if @tcpServerThread
118         @tcpServerThread.raise "stop"
119       end
120     }
121   end

I'm open to any ideas or suggestions. Thanks!
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.