永井@知能.九工大です.

From: Hidetoshi NAGAI <nagai / ai.kyutech.ac.jp>
Subject: [ruby-dev:21833] pthread trouble on tcltklib (Re: ruby-tk hangs when exception is raised)
Date: Wed, 5 Nov 2003 12:46:50 +0900
Message-ID: <20031105.124645.74739734.nagai / ai.kyutech.ac.jp>
> tcltklib.c 側での対処をあきらめて,
> Ruby 本体の eval.c と signal.c への patch として作ってみました.
> これで GC や Thread switching が生じても落ちずに済んでいるようです.
> とりあえずのテスト用なので,#ifdef などではくくっていません.

テストしやすいように,configure --with-pthread-ext で
指定できるように作り直しました.
eval.c の方の変更は --with-pthread-ext を指定しない限りは
従来通りのはずです.
signal.c の方は変更されてしまいますが,問題は生じないはずです.
お試し下さい.

Index: configure.in
===================================================================
RCS file: /src/ruby/configure.in,v
retrieving revision 1.189
diff -u -r1.189 configure.in
--- configure.in	31 Oct 2003 03:58:20 -0000	1.189
+++ configure.in	5 Nov 2003 07:56:14 -0000
@@ -323,6 +323,7 @@
 			if test "$rb_cv_supplementary_lib_c_r" = yes; then
 				MAINLIBS="-lc_r $MAINLIBS"			
 			else
+				AC_DEFINE(HAVE_LIBPTHREAD)
 				MAINLIBS="-pthread $MAINLIBS"			
 				CFLAGS="-D_THREAD_SAFE $CFLAGS"
 			fi
@@ -663,6 +664,11 @@
 
 dnl default value for $KANJI
 DEFAULT_KCODE="KCODE_NONE"
+
+AC_ARG_WITH(pthread-ext, 
+	[  --with-pthread-ext      use pthread library on external modules ],
+	[AC_CHECK_LIB(pthread, pthread_mutex_trylock)
+	 AC_DEFINE(USE_PTHREAD_EXTLIB)])
 
 AC_ARG_WITH(default-kcode, 
 	[  --with-default-kcode=CODE specify default value for \$KCODE (utf8|euc|sjis|none)], 
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 07:56:15 -0000
@@ -33,6 +33,10 @@
 #include "st.h"
 #include "dln.h"
 
+#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB)
+#include <pthread.h>
+#endif
+
 #ifdef __APPLE__
 #include <crt_externs.h>
 #endif
@@ -8604,6 +8618,11 @@
     return test;
 }
 
+#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB)
+static pthread_t thid;
+static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
 void
 rb_thread_schedule()
 {
@@ -8620,6 +8639,9 @@
     int n, max;
     int need_select = 0;
     int select_timeout = 0;
+#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB)
+    int st;
+#endif
 
     rb_thread_pending = 0;
     if (curr_thread == curr_thread->next
@@ -8629,6 +8651,16 @@
     next = 0;
     curr = curr_thread;		/* starting thread */
 
+#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB)
+    if ((st = pthread_mutex_trylock(&mtx)) == EBUSY) {
+	if (pthread_self() != thid) {
+	    return;
+	}
+    } else {
+	thid = pthread_self();
+    }
+#endif
+
     while (curr->status == THREAD_KILLED) {
 	curr = curr->prev;
     }
@@ -8826,12 +8858,22 @@
     }
     next->wait_for = 0;
     if (next->status == THREAD_RUNNABLE && next == curr_thread) {
+#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB)
+	if (st != EBUSY) {
+	    pthread_mutex_unlock(& mtx);
+	}
+#endif
 	return;
     }
 
     /* context switch */
     if (curr == curr_thread) {
 	if (THREAD_SAVE_CONTEXT(curr)) {
+#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB)
+	    if (st != EBUSY) {
+		pthread_mutex_unlock(& mtx);
+	    }
+#endif
 	    return;
 	}
     }
@@ -8841,9 +8883,19 @@
 	if (!(next->flags & THREAD_TERMINATING)) {
 	    next->flags |= THREAD_TERMINATING;
 	    /* terminate; execute ensure-clause if any */
+#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB)
+	    if (st != EBUSY) {
+		pthread_mutex_unlock(& mtx);
+	    }
+#endif
 	    rb_thread_restore_context(next, RESTORE_FATAL);
 	}
     }
+#if defined(HAVE_LIBPTHREAD) && defined(USE_PTHREAD_EXTLIB)
+    if (st != EBUSY) {
+	pthread_mutex_unlock(& mtx);
+    }
+#endif
     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 07:56:15 -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