Forum: Ruby-dev [ruby-trunk - Bug #7455][Assigned] Queue#popで待っている間にtrapに入りその時にQueue#pushされると、Queue#popから戻ってこなくなる。

Posted by tarui (Masaya Tarui) (Guest)
on 2012-11-28 14:37
(Received via mailing list)
Issue #7455 has been reported by tarui (Masaya Tarui).

----------------------------------------
Bug #7455: 
Queue#popで待っている間にtrapに入りその時にQueue#pushされると、Queue#popから戻ってこなくなる。
https://bugs.ruby-lang.org/issues/7455

Author: tarui (Masaya Tarui)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-11-28 trunk 37937) [x86_64-linux]


以下スクリプトを実行すると期待したように終わらずに、deadlockしてしまいます。
ささださんよろしく。
--

require 'thread'

que = Queue.new
th = Thread.new{
  sleep 0.1
  Process.kill(:INT,$$)
  sleep 0.1
  que.push 2
}
Signal.trap :INT do
  p :trap_task
  123456**100000 / 456 ** 10000
  p :trap_task_end
end
puts "que.pop"
p que.pop
puts "success!"
Posted by kosaki (Motohiro KOSAKI) (Guest)
on 2012-11-28 14:48
(Received via mailing list)
Issue #7455 has been updated by kosaki (Motohiro KOSAKI).


とりあえず原因を書いておくと

1. que.popで、mutex.sleepが呼ばれ、結局sleep_forever()が呼ばれる。ここで一旦 status = 
THREAD_STOPPED_FOREVERになる
2. Process.kill をうけて status = THREAD_RUNNABLEにしてトラップハンドラを実行はじめる
3. que.push を呼ぶが、main threadはすでに thread runnableなので何もおこらず
4. サブスレッド死ぬ
5. trap抜けたところで rb_threadptr_execute_interrupt()内の th->status = 
prev_status; の処理によって、
   statusがTHREAD_STOPPED_FOREVERに戻る
6.sleep_forever() は status != THREAD_RUNNABLE 
の場合sleepを再実行するので、ここでデッドロックチェック
   唯一残っているスレッドであるメインスレッドが THREAD_STOPPED_FOREVERなので、めでたくチェックにひっかかり強制終了

ささださん、よろしく



----------------------------------------
Bug #7455: 
Queue#popで待っている間にtrapに入りその時にQueue#pushされると、Queue#popから戻ってこなくなる。
https://bugs.ruby-lang.org/issues/7455#change-34084

Author: tarui (Masaya Tarui)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category: core
Target version: 2.0.0
ruby -v: ruby 2.0.0dev (2012-11-28 trunk 37937) [x86_64-linux]


以下スクリプトを実行すると期待したように終わらずに、deadlockしてしまいます。
ささださんよろしく。
--

require 'thread'

que = Queue.new
th = Thread.new{
  sleep 0.1
  Process.kill(:INT,$$)
  sleep 0.1
  que.push 2
}
Signal.trap :INT do
  p :trap_task
  123456**100000 / 456 ** 10000
  p :trap_task_end
end
puts "que.pop"
p que.pop
puts "success!"
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.