summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--eval.c9
-rw-r--r--ruby.h8
-rw-r--r--signal.c129
4 files changed, 146 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 600c1fe64f..aae579a949 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Wed Jun 21 17:32:31 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * signal.c (ruby_nativethread_signal, posix_nativethread_signal,
+ sigsend_to_ruby_thread, install_nativethread_sighandler):
+ nativethread-support on signal handler (backport from 1.9).
+
+ * ruby.h (HAVE_NATIVETHREAD_KILL): ditto.
+
+ * eval.c (ruby_native_thread_kill): ditto.
+
Wed Jun 21 08:39:54 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* lib/xmlrpc/create.rb (XMLRPC::Create::conv2value): merge Date
diff --git a/eval.c b/eval.c
index 96042aefb1..4e16d2aceb 100644
--- a/eval.c
+++ b/eval.c
@@ -1342,6 +1342,15 @@ int
is_ruby_native_thread() {
return NATIVETHREAD_EQUAL(ruby_thid, NATIVETHREAD_CURRENT());
}
+
+# ifdef HAVE_NATIVETHREAD_KILL
+void
+ruby_native_thread_kill(sig)
+ int sig;
+{
+ NATIVETHREAD_KILL(ruby_thid, sig);
+}
+# endif
#endif
void
diff --git a/ruby.h b/ruby.h
index c23a60daa8..a4a8753ee9 100644
--- a/ruby.h
+++ b/ruby.h
@@ -696,6 +696,9 @@ typedef pthread_t rb_nativethread_t;
# define NATIVETHREAD_CURRENT() pthread_self()
# define NATIVETHREAD_EQUAL(t1,t2) pthread_equal((t1),(t2))
# define HAVE_NATIVETHREAD
+
+# define NATIVETHREAD_KILL(th,sig) pthread_kill((th),(sig))
+# define HAVE_NATIVETHREAD_KILL
#elif defined(_WIN32) || defined(_WIN32_WCE)
typedef DWORD rb_nativethread_t;
# define NATIVETHREAD_CURRENT() GetCurrentThreadId()
@@ -703,10 +706,13 @@ typedef DWORD rb_nativethread_t;
# define HAVE_NATIVETHREAD
#endif
#ifdef HAVE_NATIVETHREAD
-RUBY_EXTERN int is_ruby_native_thread();
+int is_ruby_native_thread _((void));
#else
#define is_ruby_native_thread() (1)
#endif
+#ifdef HAVE_NATIVETHREAD_KILL
+void ruby_native_thread_kill _((int));
+#endif
#if defined(__cplusplus)
#if 0
diff --git a/signal.c b/signal.c
index fc8d95776f..ffcb17b6eb 100644
--- a/signal.c
+++ b/signal.c
@@ -304,6 +304,7 @@ static struct {
int safe;
} trap_list[NSIG];
static rb_atomic_t trap_pending_list[NSIG];
+static char rb_trap_accept_nativethreads[NSIG];
rb_atomic_t rb_trap_pending;
rb_atomic_t rb_trap_immediate;
int rb_prohibit_interrupt = 1;
@@ -335,21 +336,23 @@ ruby_signal(signum, handler)
{
struct sigaction sigact, old;
+ rb_trap_accept_nativethreads[signum] = 0;
+
sigact.sa_handler = handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
-#if defined(SA_RESTART)
+# if defined(SA_RESTART)
/* All other signals but VTALRM shall restart restartable syscall
VTALRM will cause EINTR to syscall if interrupted.
*/
if (signum != SIGVTALRM) {
sigact.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
}
-#endif
-#ifdef SA_NOCLDWAIT
+# endif
+# ifdef SA_NOCLDWAIT
if (signum == SIGCHLD && handler == SIG_IGN)
sigact.sa_flags |= SA_NOCLDWAIT;
-#endif
+# endif
sigaction(signum, &sigact, &old);
return old.sa_handler;
}
@@ -361,9 +364,46 @@ posix_signal(signum, handler)
{
ruby_signal(signum, handler);
}
-#else
-#define ruby_signal(sig,handler) signal((sig),(handler))
-#endif
+
+# ifdef HAVE_NATIVETHREAD
+static sighandler_t
+ruby_nativethread_signal(signum, handler)
+ int signum;
+ sighandler_t handler;
+{
+ sighandler_t old;
+
+ old = ruby_signal(signum, handler);
+ rb_trap_accept_nativethreads[signum] = 1;
+ return old;
+}
+
+void
+posix_nativethread_signal(signum, handler)
+ int signum;
+ sighandler_t handler;
+{
+ ruby_nativethread_signal(signum, handler);
+}
+# endif
+
+#else /* !POSIX_SIGNAL */
+#define ruby_signal(sig,handler) (rb_trap_accept_nativethreads[sig] = 0, signal((sig),(handler)))
+
+# ifdef HAVE_NATIVETHREAD
+static sighandler_t
+ruby_nativethread_signal(signum, handler)
+ int signum;
+ sighandler_t handler;
+{
+ sighandler_t old;
+
+ old = signal(signum, handler);
+ rb_trap_accept_nativethreads[signum] = 1;
+ return old;
+}
+# endif
+#endif /* POSIX_SIGNAL */
static void signal_exec _((int sig));
static void
@@ -394,11 +434,36 @@ signal_exec(sig)
break;
}
}
+ else if (trap_list[sig].cmd == Qundef) {
+ rb_thread_signal_exit();
+ }
else {
rb_thread_trap_eval(trap_list[sig].cmd, sig, trap_list[sig].safe);
}
}
+#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
+static void
+sigsend_to_ruby_thread(int sig)
+{
+# ifdef HAVE_SIGPROCMASK
+ sigset_t mask, old_mask;
+# else
+ int mask, old_mask;
+# endif
+
+# ifdef HAVE_SIGPROCMASK
+ sigfillset(&mask);
+ sigprocmask(SIG_BLOCK, &mask, &old_mask);
+# else
+ mask = sigblock(~0);
+ sigsetmask(mask);
+# endif
+
+ ruby_native_thread_kill(sig);
+}
+#endif
+
static RETSIGTYPE sighandler _((int));
static RETSIGTYPE
sighandler(sig)
@@ -414,11 +479,22 @@ sighandler(sig)
rb_bug("trap_handler: Bad signal %d", sig);
}
+#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
+ if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
+ sigsend_to_ruby_thread(sig);
+ return;
+ }
+#endif
+
#if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
- ruby_signal(sig, sighandler);
+ if (rb_trap_accept_nativethreads[sig]) {
+ ruby_nativethread_signal(sig, sighandler);
+ } else {
+ ruby_signal(sig, sighandler);
+ }
#endif
- if (ATOMIC_TEST(rb_trap_immediate)) {
+ if (trap_list[sig].cmd == 0 && ATOMIC_TEST(rb_trap_immediate)) {
IN_MAIN_CONTEXT(signal_exec, sig);
ATOMIC_SET(rb_trap_immediate, 1);
}
@@ -434,6 +510,13 @@ static RETSIGTYPE
sigbus(sig)
int sig;
{
+#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
+ if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
+ sigsend_to_ruby_thread(sig);
+ return;
+ }
+#endif
+
rb_bug("Bus Error");
}
#endif
@@ -444,6 +527,13 @@ static RETSIGTYPE
sigsegv(sig)
int sig;
{
+#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
+ if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
+ sigsend_to_ruby_thread(sig);
+ return;
+ }
+#endif
+
rb_bug("Segmentation fault");
}
#endif
@@ -772,6 +862,27 @@ install_sighandler(signum, handler)
}
}
+#ifdef HAVE_NATIVETHREAD
+static void
+install_nativethread_sighandler(signum, handler)
+ int signum;
+ sighandler_t handler;
+{
+ sighandler_t old;
+ int old_st;
+
+ old_st = rb_trap_accept_nativethreads[signum];
+ old = ruby_nativethread_signal(signum, handler);
+ if (old != SIG_DFL) {
+ if (old_st) {
+ ruby_nativethread_signal(signum, old);
+ } else {
+ ruby_signal(signum, old);
+ }
+ }
+}
+#endif
+
static void
init_sigchld(sig)
int sig;