From: nobu@...
Date: 2017-07-27T04:13:50+00:00
Subject: [ruby-dev:50187] [Ruby trunk Bug#13768] SIGCHLD and Thread	dead-lock problem

Issue #13768 has been updated by nobu (Nobuyoshi Nakada).

Description updated

`Signal.trap`を設定していたら常にデッドロックではない、とすべきというところでしょうか。
まぁ設定していなくても実際に受けとればデッドロックを抜けはするのですが。

```diff
diff --git c/signal.c i/signal.c
index 2e69cf08ac..3b026724f9 100644
--- c/signal.c
+++ i/signal.c
@@ -1235,6 +1235,7 @@ trap(int sig, sighandler_t func, VALUE command)
     sighandler_t oldfunc;
     VALUE oldcmd;
     rb_vm_t *vm = GET_VM();
+    int handle_count = 0;
 
     /*
      * Be careful. ruby_signal() and trap_list[sig].cmd must be changed
@@ -1261,8 +1262,20 @@ trap(int sig, sighandler_t func, VALUE command)
 	break;
       case Qundef:
 	oldcmd = rb_str_new2("EXIT");
+      default:
+	--handle_count;
 	break;
     }
+    switch (command) {
+      case 0: case Qtrue: case Qnil:
+	break;
+      default:
+	++handle_count;
+	break;
+    }
+    if (vm->trap_count + handle_count < 0) rb_fatal("trap_count underflow");
+
+    vm->trap_count += handle_count;
 
     vm->trap_list[sig].cmd = command;
     vm->trap_list[sig].safe = rb_safe_level();
diff --git c/thread.c i/thread.c
index b7ee1d8d9b..fdb9221fd3 100644
--- c/thread.c
+++ i/thread.c
@@ -4947,6 +4947,7 @@ rb_check_deadlock(rb_vm_t *vm)
     if (vm_living_thread_num(vm) > vm->sleeper) return;
     if (vm_living_thread_num(vm) < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
     if (patrol_thread && patrol_thread != GET_THREAD()) return;
+    if (vm->trap_count > 0) return;
 
     list_for_each(&vm->living_threads, th, vmlt_node) {
 	if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th)) {
diff --git c/vm_core.h i/vm_core.h
index c23f50690e..a2fa25ad50 100644
--- c/vm_core.h
+++ i/vm_core.h
@@ -550,6 +550,7 @@ typedef struct rb_vm_struct {
 	VALUE cmd;
 	int safe;
     } trap_list[RUBY_NSIG];
+    int trap_count;
 
     /* hook */
     rb_hook_list_t event_hooks;
```

----------------------------------------
Bug #13768: SIGCHLD and Thread dead-lock problem
https://bugs.ruby-lang.org/issues/13768#change-65955

* Author: keiju (Keiju Ishitsuka)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: 
* Backport: 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN
----------------------------------------
 けいじゅ@いしつかです.
 
 下記のプログラムを実行するとThreadがデッドロックしたと例外が発生します.
 # コメント部分をはずせば, デッドロックはしません
 
 シグナルのtrapが絡むときのデッドロックの検知に問題があるのではないかと
 思いますがいかがでしょう? 

 ```
 % ruby -v
 ruby 2.5.0dev (2017-07-25 trunk 59417) [i686-linux]
 ```
 ```ruby
 q = Queue.new
 p = Queue.new
 
 trap(:SIGCHLD) do
   puts "SIGCHLD"
   q.push 1
 end
 
 Thread.start do
   Process.spawn("/bin/sleep 1")
 end
 
 #Thread.start do
 #  loop do
 #    sleep 100
 #  end
 #end
 
 th = Thread.start{
   p.push q.pop
 }
 
 p.pop
 ```
 __
 ---------------------------------------------------->> 石塚 圭樹 <<---
 ---------------------------------->> e-mail: keiju@ishitsuka.com <<---



-- 
https://bugs.ruby-lang.org/