From: f-miura@... (MIURA, Fumiaki) Date: 2010-01-18T11:40:44+09:00 Subject: [ruby-dev:40109] Re: [Bug #2603] NetBSD 5.0以降でpthreadの処理に由来する不具合 --Multipart_Mon_Jan_18_11:40:44_2010-1 Content-Type: text/plain; charset=ISO-2022-JP NTTレゾナントの三浦です。 改良版かもしれないfork patchその2を作ってみました。 ■前回の反省点とその対応: [ruby-dev:40074] > (1) fork(2)した子プロセスは非同期シグナルに対して安全な関数だけを使 > 用でき、pthread_*()な関数も使用できません これはダメダメなままです。 [ruby-dev:40091] > 本件の方針を確認させてもらえませんか? 三浦の思いとしては、規格には(我慢してもらえる範囲で)目をつぶってもらっ て、なるべく使えるものになって欲しい。もしくは、「rubyの仕様でそこは知 らん」と明確化できるのでもいいかも。 [ruby-dev:40092] > 3. fork(2)した子プロセスがexec(3)せずに動作を続ける場合 たとえば、rubyの管理下にないthreadが行うmalloc(3)の類の影響はそのまま 残り、それを使えるthreadは存在しなくなります。つまりメモリーリーク。 それでも使えるようにがんばるものか、やるなというのか。 ・最小の手続きが済んだらすぐexec(3)(もしくはexit(3))しろと推奨 ・close on execはやっとけ ぐらいは必要そう。 [ruby-dev:40096] > このpatch-2、公開 API である rb_thread_stop_timer の引数を void から > int に変えているんですが、大丈夫ですか。 変えないのを作ってみました。その代わり神戸さんpatch-2より規格的に怪し い。 [ruby-dev:40102] > MacOS X 対策じゃないかなぁ。 > [ruby-core:9848] fork(2)の前には*rubyのthreadは*1つになります。でもそれ以外のthreadを 使いたいから--enable-pthreadするんじゃないのかなあ? ■今回のpatchの基本方針。 [ruby-dev:40051]に[ruby-dev:38996]のパクリました。 違いはpthread_mutex_destroy()とpthread_mutex_init()の追加です。POSIX的 な怪しさはなくなっていませんが、減ってると期待しています。 32bitと64bitのlinuxで試した範囲ではこれで(も)大丈夫そうです。 -- ▽R← 三浦史光 X;M R←+/,(?1↑ρM)/M←X≠.- 運命 X▽ --Multipart_Mon_Jan_18_11:40:44_2010-1 Content-Type: text/plain; charset=US-ASCII --- eval.c 2010/01/07 01:03:01 1.1 +++ eval.c 2010/01/18 01:28:53 @@ -12292,9 +12292,15 @@ pthread_t thread; } time_thread = {PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER}; +static inline void pthread_cleanup_force(pthread_mutex_t *lock) +{ + pthread_mutex_unlock(lock); + pthread_mutex_destroy(lock); +} + #define safe_mutex_lock(lock) \ pthread_mutex_lock(lock); \ - pthread_cleanup_push((void (*)_((void *)))pthread_mutex_unlock, lock) + pthread_cleanup_push((void (*)_((void *)))pthread_cleanup_force, lock) static void* thread_timer(dummy) @@ -12329,6 +12335,17 @@ 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 +12360,8 @@ 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(rb_thread_stop_timer, + rb_thread_stop_timer_atfork, rb_thread_stop_timer_atfork); pthread_cond_wait(&start, &time_thread.lock); } pthread_cleanup_pop(1); --Multipart_Mon_Jan_18_11:40:44_2010-1--