青木です。

以下のようなプログラムを実行して SIGTERM を送っても、
$stdin.gets が戻るまでシグナルハンドラが実行されません。

  Signal.trap(:TERM) { puts 'TERM'; exit }
  puts $$
  while true
    p $stdin.gets()
  end

pure Ruby 版の FastCGI サーバでこのようなコードが必要になりました。
FastCGI サーバは常に stdin を待ち受けますが、SIGUSR1 でリジューム、
SIGTERM で exit 0 をするという規約があるので、I/O 待ちをしつつ
リアルタイムでシグナルも受け付ける必要があります。

これが動作しないと事実上シグナルが効かなくなるので、例えば Apache
が停止しても ruby プロセスだけが残ってしまうという問題があります。
うちのサーバでは毎日ログをローテートするたびに ruby プロセスが死に
損なっていました。

なお、上記のコードが動作しない原因は [ruby-dev:25003] で導入された
signal.c:1.55 がそのままになっていることだと思います。そのあとの
展開でこのリビジョンの変更は不要になっているはずなので、巻き戻す
べきではないでしょうか。
-------------------------------------------------------------------
青木峰郎

Thu Feb 24 09:08:10 2005 Minero Aoki <aamine / loveruby.net> * signal.c: revert rev 1.55; allow pure ruby signal handler in I/O operation.
Index: signal.c =================================================================== RCS file: /var/cvs/src/ruby/signal.c,v retrieving revision 1.57 diff -u -r1.57 signal.c --- signal.c 22 Feb 2005 14:50:33 -0000 1.57 +++ signal.c 24 Feb 2005 00:02:31 -0000 @@ -465,7 +465,7 @@ } #endif - if (trap_list[sig].cmd == 0 && ATOMIC_TEST(rb_trap_immediate)) { + if (ATOMIC_TEST(rb_trap_immediate)) { IN_MAIN_CONTEXT(signal_exec, sig); ATOMIC_SET(rb_trap_immediate, 1); }