Miniruby -e 'Process.kill(:INT, $$)' hang under cron

Issue #9820 has been updated by Nobuyoshi N…

元々シグナルがすぐ配送されるとは限らないわけで、とりあえずタイムアウトをつけてみるのはどうでしょうか。

diff --git i/thread.c w/thread.c
index dfa91a8..209aff1 100644
--- i/thread.c
+++ w/thread.c
@@ -5180,10 +5180,11 @@ ruby_kill(rb_pid_t pid, int sig)
      * delivered immediately and synchronously.
      */
     if ((sig != 0) && (th == vm->main_thread) && (pid == getpid())) {
+  static const struct timespec limit = {0, 1000*1000}; /* 1ms */
   GVL_UNLOCK_BEGIN();
   native_mutex_lock(&th->interrupt_lock);
   err = kill(pid, sig);
-  native_cond_wait(&th->interrupt_cond, &th->interrupt_lock);
+  native_cond_timedwait(&th->interrupt_cond, &th->interrupt_lock, 
&limit);
   native_mutex_unlock(&th->interrupt_lock);
   GVL_UNLOCK_END();
     }

Bug #9820: miniruby -e ‘Process.kill(:INT, $$)’ hang under cron

  • Author: Akira T.
  • Status: Open
  • Priority: Normal
  • Assignee:
  • Category:
  • Target version:
  • ruby -v: ruby 2.2.0dev (2014-05-09 trunk 45884) [x86_64-linux]
  • Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN

最近、しばたさんが運用を始めた chkbuild で、
TestBeginEndBlock#test_propagate_signaled が hang しています。
http://chkbuild002.hsbt.org/chkbuild/ruby-trunk/log/20140509T060013Z.fail.html.gz

調べて再現コードを小さくしていった結果、

miniruby -e ‘Process.kill(:INT, $$)’

というのを cron から動かしたときは hang し、
端末から動かしたときは hang しない、ということが判明しました。

strace した結果をみると、
cron 下では timer thread が prctl の直後に poll を呼び出してそれが終わらないという挙動なのに対し、
端末ではそのあたりで context switch が起きている、ような気がします。

strace の結果を strace.cron.log と strace.term.log として添付します。

なにかわかるひとはいますでしょうか?

% ./miniruby -v
ruby 2.2.0dev (2014-05-09 trunk 45884) [x86_64-linux]
% uname -mrsv
Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.54-2 x86_64
% lsb_release -idrc
Distributor ID:  Debian
Description:  Debian GNU/Linux 7.5 (wheezy)
Release:  7.5
Codename:  wheezy

なお、コミッタならしばたさんに頼むとそのマシンにアカウントを作ってくれる模様です。

—Files--------------------------------
strace.cron.log (15.8 KB)
strace.term.log (17.6 KB)