From: f-miura@... (MIURA, Fumiaki) Date: 2010-01-12T13:57:54+09:00 Subject: [ruby-dev:40051] Bug #1872 --Multipart_Tue_Jan_12_13:57:52_2010-1 Content-Type: text/plain; charset=ISO-2022-JP NTTレゾナントの三浦です。 Bug #1872 [ruby-dev:38996]の対策をしてみました。 ■問題の復習 --enable-pthread版でruby -e 'Process.fork{p system("ls")}'とかすると fork(2)の後で固まることがある。 ■解析結果 ・fork()でできた新しいプロセスの中にはmain thread以外のthreadは存在し ない。当然、SIGVTALRMしてくれるthreadもいない。 ・該threadの制御にsafe_mutex_lock()を使う。safe_mutex_lock()のsafeたる 所以は、lockを保持しているthreadが終了する時にlockを解放するから。そ のためにpthread_cleanup_push()を使う。 ・fork()の時には該threadが終了してはいないため、lock解放操作は行われな い。 ・fork()直後にrb_thread_stop_timer()が呼び出され、該lockを操作しようと して刺さることがある†。 -- †pthread_mutex_tとpthread_mutex_lock()の実現に依存する。刺さらない環 境もあるかも。三浦が使った環境ではpthread_mutex_trylock()でも刺さる。 ■対策 ・fork()直後に該データを初期化する。fork()直後なので調べなくてもそうい うthreadはいない。 ruby-1.8.7-p248だとこういうpatchでいいと思います。関数名以外は。 一晩動かしても刺さらなくなりました。 --Multipart_Tue_Jan_12_13:57:52_2010-1 Content-Type: text/plain; charset=US-ASCII --- eval.c 2010/01/07 01:03:01 1.1 +++ eval.c 2010/01/12 04:22:08 @@ -12329,6 +12329,16 @@ return NULL; } +/* fix inconsistent data */ +static void +rb_thread_stop_timer_atfork(void) +{ + if (!thread_init) return; + (void)pthread_cond_init(&time_thread.cond, NULL); + (void)pthread_mutex_init(&time_thread.lock, NULL); + thread_init = 0; +} + void rb_thread_start_timer() { @@ -12343,7 +12353,7 @@ safe_mutex_lock(&time_thread.lock); if (pthread_create(&time_thread.thread, 0, thread_timer, args) == 0) { thread_init = 1; - pthread_atfork(0, 0, rb_thread_stop_timer); + pthread_atfork(0, 0, rb_thread_stop_timer_atfork); pthread_cond_wait(&start, &time_thread.lock); } pthread_cleanup_pop(1); --Multipart_Tue_Jan_12_13:57:52_2010-1--