From: Hidetoshi NAGAI Date: 2003-11-05T12:46:50+09:00 Subject: [ruby-dev:21833] pthread trouble on tcltklib (Re: ruby-tk hangs when exception is raised) 永井@知能.九工大です. tcltklib.c 側での対処をあきらめて, Ruby 本体の eval.c と signal.c への patch として作ってみました. これで GC や Thread switching が生じても落ちずに済んでいるようです. とりあえずのテスト用なので,#ifdef などではくくっていません. 試してみていただけないでしょうか. # もしかすると,これで pthread 依存のライブラリへの耐性が # 少し上がっているかも...ってほどは世の中甘くないか.(^_^) Index: Makefile.in =================================================================== RCS file: /src/ruby/Makefile.in,v retrieving revision 1.50 diff -u -r1.50 Makefile.in --- Makefile.in 5 Nov 2003 02:15:26 -0000 1.50 +++ Makefile.in 5 Nov 2003 03:33:23 -0000 @@ -26,7 +26,7 @@ LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@ EXTLDFLAGS = XLDFLAGS = @XLDFLAGS@ $(EXTLDFLAGS) -EXTLIBS = +EXTLIBS = -lpthread LIBS = @LIBS@ $(EXTLIBS) MISSING = @LIBOBJS@ @ALLOCA@ LDSHARED = @LIBRUBY_LDSHARED@ Index: eval.c =================================================================== RCS file: /src/ruby/eval.c,v retrieving revision 1.583 diff -u -r1.583 eval.c --- eval.c 4 Nov 2003 09:13:56 -0000 1.583 +++ eval.c 5 Nov 2003 03:33:27 -0000 @@ -32,6 +32,7 @@ #include #include "st.h" #include "dln.h" +#include #ifdef __APPLE__ #include @@ -8604,6 +8615,9 @@ return test; } +static pthread_t thid; +static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; + void rb_thread_schedule() { @@ -8621,6 +8635,8 @@ int need_select = 0; int select_timeout = 0; + int st; + rb_thread_pending = 0; if (curr_thread == curr_thread->next && curr_thread->status == THREAD_RUNNABLE) @@ -8629,6 +8645,14 @@ next = 0; curr = curr_thread; /* starting thread */ + if ((st = pthread_mutex_trylock(&mtx)) == EBUSY) { + if (pthread_self() != thid) { + return; + } + } else { + thid = pthread_self(); + } + while (curr->status == THREAD_KILLED) { curr = curr->prev; } @@ -8826,12 +8850,18 @@ } next->wait_for = 0; if (next->status == THREAD_RUNNABLE && next == curr_thread) { + if (st != EBUSY) { + pthread_mutex_unlock(& mtx); + } return; } /* context switch */ if (curr == curr_thread) { if (THREAD_SAVE_CONTEXT(curr)) { + if (st != EBUSY) { + pthread_mutex_unlock(& mtx); + } return; } } @@ -8841,8 +8871,14 @@ if (!(next->flags & THREAD_TERMINATING)) { next->flags |= THREAD_TERMINATING; /* terminate; execute ensure-clause if any */ + if (st != EBUSY) { + pthread_mutex_unlock(& mtx); + } rb_thread_restore_context(next, RESTORE_FATAL); } + } + if (st != EBUSY) { + pthread_mutex_unlock(& mtx); } rb_thread_restore_context(next, RESTORE_NORMAL); } Index: signal.c =================================================================== RCS file: /src/ruby/signal.c,v retrieving revision 1.48 diff -u -r1.48 signal.c --- signal.c 1 Oct 2003 15:14:22 -0000 1.48 +++ signal.c 5 Nov 2003 03:33:27 -0000 @@ -711,6 +711,7 @@ { #ifndef MACOS_UNUSE_SIGNAL VALUE mSignal = rb_define_module("Signal"); + VALUE oldsig; rb_define_global_function("trap", sig_trap, -1); rb_define_module_function(mSignal, "trap", sig_trap, -1); @@ -741,6 +742,21 @@ #endif #ifdef SIGPIPE install_sighandler(SIGPIPE, sigpipe); +#endif + +#ifdef SIGCLD + oldsig = rb_funcall(rb_mKernel, rb_intern("trap"), 2, + INT2FIX(SIGCLD), rb_str_new2("SIG_DFL")); + if (oldsig != Qnil) { + rb_funcall(rb_mKernel, rb_intern("trap"), 2, INT2FIX(SIGCLD), oldsig); + } +#endif +#ifdef SIGCHLD + oldsig = rb_funcall(rb_mKernel, rb_intern("trap"), 2, + INT2FIX(SIGCHLD), rb_str_new2("SIG_DFL")); + if (oldsig != Qnil) { + rb_funcall(rb_mKernel, rb_intern("trap"), 2, INT2FIX(SIGCHLD), oldsig); + } #endif #endif /* MACOS_UNUSE_SIGNAL */ } -- 永井 秀利 (九工大 知能情報) nagai@ai.kyutech.ac.jp