From 5ed246f1d37571ce482bf3fcbb28457d8dd5cf06 Mon Sep 17 00:00:00 2001 From: nagai Date: Mon, 10 Jul 2006 05:02:00 +0000 Subject: [PATCH] * signal.c (ruby_nativethread_signal, posix_nativethread_signal, sigsend_to_ruby_thread, install_nativethread_sighandler): nativethread-support on signal handler. RE-backport from 1.9. * ruby.h (HAVE_NATIVETHREAD_KILL): ditto. * eval.c (ruby_native_thread_kill): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@10502 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 ++++ eval.c | 9 ++++ ruby.h | 8 +++- signal.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 155 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b46f73df4..ebf78f0bac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Mon Jul 10 13:58:40 2006 Hidetoshi NAGAI + + * signal.c (ruby_nativethread_signal, posix_nativethread_signal, + sigsend_to_ruby_thread, install_nativethread_sighandler): + nativethread-support on signal handler. RE-backport from 1.9. + + * ruby.h (HAVE_NATIVETHREAD_KILL): ditto. + + * eval.c (ruby_native_thread_kill): ditto. + Mon Jul 10 10:54:14 2006 Ryan Davis * lib/rdoc/parsers/parse_f95.rb: massive overhaul from Yasuhiro diff --git a/eval.c b/eval.c index 9a909557e8..652a33defc 100644 --- a/eval.c +++ b/eval.c @@ -1343,6 +1343,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..f66fd3673c 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(BSD_SIGNAL) && !defined(POSIX_SIGNAL) - ruby_signal(sig, sighandler); +#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 (ATOMIC_TEST(rb_trap_immediate)) { +#if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL) + if (rb_trap_accept_nativethreads[sig]) { + ruby_nativethread_signal(sig, sighandler); + } else { + ruby_signal(sig, sighandler); + } +#endif + + 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,35 @@ install_sighandler(signum, handler) } } +#if 0 +/* + * If you write a handler which works on any native thread + * (even if the thread is NOT a ruby's one), please enable + * this function and use it to install the handler, instead + * of `install_sighandler()'. + */ +#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 +#endif + static void init_sigchld(sig) int sig;