Ruby  1.9.3p537(2014-02-19revision0)
signal.c
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   signal.c -
00004 
00005   $Author$
00006   created at: Tue Dec 20 10:13:44 JST 1994
00007 
00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
00009   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
00010   Copyright (C) 2000  Information-technology Promotion Agency, Japan
00011 
00012 **********************************************************************/
00013 
00014 #include "ruby/ruby.h"
00015 #include "vm_core.h"
00016 #include <signal.h>
00017 #include <stdio.h>
00018 #include <errno.h>
00019 #include "ruby_atomic.h"
00020 #ifdef HAVE_UNISTD_H
00021 # include <unistd.h>
00022 #endif
00023 
00024 #if !defined(_WIN32) && !defined(HAVE_GCC_ATOMIC_BUILTINS)
00025 rb_atomic_t
00026 ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val)
00027 {
00028     rb_atomic_t old = *ptr;
00029     *ptr = val;
00030     return old;
00031 }
00032 
00033 rb_atomic_t
00034 ruby_atomic_compare_and_swap(rb_atomic_t *ptr, rb_atomic_t cmp,
00035                              rb_atomic_t newval)
00036 {
00037     rb_atomic_t old = *ptr;
00038     if (old == cmp) {
00039         *ptr = newval;
00040     }
00041     return old;
00042 }
00043 #endif
00044 
00045 #if defined(__BEOS__) || defined(__HAIKU__)
00046 #undef SIGBUS
00047 #endif
00048 
00049 #ifdef HAVE_PTHREAD_SIGMASK
00050 #define USE_TRAP_MASK 1
00051 #else
00052 #define USE_TRAP_MASK 0
00053 #endif
00054 
00055 #ifndef NSIG
00056 # define NSIG (_SIGMAX + 1)      /* For QNX */
00057 #endif
00058 
00059 static const struct signals {
00060     const char *signm;
00061     int  signo;
00062 } siglist [] = {
00063     {"EXIT", 0},
00064 #ifdef SIGHUP
00065     {"HUP", SIGHUP},
00066 #endif
00067     {"INT", SIGINT},
00068 #ifdef SIGQUIT
00069     {"QUIT", SIGQUIT},
00070 #endif
00071 #ifdef SIGILL
00072     {"ILL", SIGILL},
00073 #endif
00074 #ifdef SIGTRAP
00075     {"TRAP", SIGTRAP},
00076 #endif
00077 #ifdef SIGIOT
00078     {"IOT", SIGIOT},
00079 #endif
00080 #ifdef SIGABRT
00081     {"ABRT", SIGABRT},
00082 #endif
00083 #ifdef SIGEMT
00084     {"EMT", SIGEMT},
00085 #endif
00086 #ifdef SIGFPE
00087     {"FPE", SIGFPE},
00088 #endif
00089 #ifdef SIGKILL
00090     {"KILL", SIGKILL},
00091 #endif
00092 #ifdef SIGBUS
00093     {"BUS", SIGBUS},
00094 #endif
00095 #ifdef SIGSEGV
00096     {"SEGV", SIGSEGV},
00097 #endif
00098 #ifdef SIGSYS
00099     {"SYS", SIGSYS},
00100 #endif
00101 #ifdef SIGPIPE
00102     {"PIPE", SIGPIPE},
00103 #endif
00104 #ifdef SIGALRM
00105     {"ALRM", SIGALRM},
00106 #endif
00107 #ifdef SIGTERM
00108     {"TERM", SIGTERM},
00109 #endif
00110 #ifdef SIGURG
00111     {"URG", SIGURG},
00112 #endif
00113 #ifdef SIGSTOP
00114     {"STOP", SIGSTOP},
00115 #endif
00116 #ifdef SIGTSTP
00117     {"TSTP", SIGTSTP},
00118 #endif
00119 #ifdef SIGCONT
00120     {"CONT", SIGCONT},
00121 #endif
00122 #ifdef SIGCHLD
00123     {"CHLD", SIGCHLD},
00124 #endif
00125 #ifdef SIGCLD
00126     {"CLD", SIGCLD},
00127 #else
00128 # ifdef SIGCHLD
00129     {"CLD", SIGCHLD},
00130 # endif
00131 #endif
00132 #ifdef SIGTTIN
00133     {"TTIN", SIGTTIN},
00134 #endif
00135 #ifdef SIGTTOU
00136     {"TTOU", SIGTTOU},
00137 #endif
00138 #ifdef SIGIO
00139     {"IO", SIGIO},
00140 #endif
00141 #ifdef SIGXCPU
00142     {"XCPU", SIGXCPU},
00143 #endif
00144 #ifdef SIGXFSZ
00145     {"XFSZ", SIGXFSZ},
00146 #endif
00147 #ifdef SIGVTALRM
00148     {"VTALRM", SIGVTALRM},
00149 #endif
00150 #ifdef SIGPROF
00151     {"PROF", SIGPROF},
00152 #endif
00153 #ifdef SIGWINCH
00154     {"WINCH", SIGWINCH},
00155 #endif
00156 #ifdef SIGUSR1
00157     {"USR1", SIGUSR1},
00158 #endif
00159 #ifdef SIGUSR2
00160     {"USR2", SIGUSR2},
00161 #endif
00162 #ifdef SIGLOST
00163     {"LOST", SIGLOST},
00164 #endif
00165 #ifdef SIGMSG
00166     {"MSG", SIGMSG},
00167 #endif
00168 #ifdef SIGPWR
00169     {"PWR", SIGPWR},
00170 #endif
00171 #ifdef SIGPOLL
00172     {"POLL", SIGPOLL},
00173 #endif
00174 #ifdef SIGDANGER
00175     {"DANGER", SIGDANGER},
00176 #endif
00177 #ifdef SIGMIGRATE
00178     {"MIGRATE", SIGMIGRATE},
00179 #endif
00180 #ifdef SIGPRE
00181     {"PRE", SIGPRE},
00182 #endif
00183 #ifdef SIGGRANT
00184     {"GRANT", SIGGRANT},
00185 #endif
00186 #ifdef SIGRETRACT
00187     {"RETRACT", SIGRETRACT},
00188 #endif
00189 #ifdef SIGSOUND
00190     {"SOUND", SIGSOUND},
00191 #endif
00192 #ifdef SIGINFO
00193     {"INFO", SIGINFO},
00194 #endif
00195     {NULL, 0}
00196 };
00197 
00198 static int
00199 signm2signo(const char *nm)
00200 {
00201     const struct signals *sigs;
00202 
00203     for (sigs = siglist; sigs->signm; sigs++)
00204         if (strcmp(sigs->signm, nm) == 0)
00205             return sigs->signo;
00206     return 0;
00207 }
00208 
00209 static const char*
00210 signo2signm(int no)
00211 {
00212     const struct signals *sigs;
00213 
00214     for (sigs = siglist; sigs->signm; sigs++)
00215         if (sigs->signo == no)
00216             return sigs->signm;
00217     return 0;
00218 }
00219 
00220 const char *
00221 ruby_signal_name(int no)
00222 {
00223     return signo2signm(no);
00224 }
00225 
00226 /*
00227  * call-seq:
00228  *    SignalException.new(sig_name)              ->  signal_exception
00229  *    SignalException.new(sig_number [, name])   ->  signal_exception
00230  *
00231  *  Construct a new SignalException object.  +sig_name+ should be a known
00232  *  signal name.
00233  */
00234 
00235 static VALUE
00236 esignal_init(int argc, VALUE *argv, VALUE self)
00237 {
00238     int argnum = 1;
00239     VALUE sig = Qnil;
00240     int signo;
00241     const char *signm;
00242 
00243     if (argc > 0) {
00244         sig = rb_check_to_integer(argv[0], "to_int");
00245         if (!NIL_P(sig)) argnum = 2;
00246         else sig = argv[0];
00247     }
00248     if (argc < 1 || argnum < argc) {
00249         rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
00250                  argc, argnum);
00251     }
00252     if (argnum == 2) {
00253         signo = NUM2INT(sig);
00254         if (signo < 0 || signo > NSIG) {
00255             rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
00256         }
00257         if (argc > 1) {
00258             sig = argv[1];
00259         }
00260         else {
00261             signm = signo2signm(signo);
00262             if (signm) {
00263                 sig = rb_sprintf("SIG%s", signm);
00264             }
00265             else {
00266                 sig = rb_sprintf("SIG%u", signo);
00267             }
00268         }
00269     }
00270     else {
00271         signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig);
00272         if (strncmp(signm, "SIG", 3) == 0) signm += 3;
00273         signo = signm2signo(signm);
00274         if (!signo) {
00275             rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
00276         }
00277         sig = rb_sprintf("SIG%s", signm);
00278     }
00279     rb_call_super(1, &sig);
00280     rb_iv_set(self, "signo", INT2NUM(signo));
00281 
00282     return self;
00283 }
00284 
00285 /*
00286  * call-seq:
00287  *    signal_exception.signo   ->  num
00288  *
00289  *  Returns a signal number.
00290  */
00291 
00292 static VALUE
00293 esignal_signo(VALUE self)
00294 {
00295     return rb_iv_get(self, "signo");
00296 }
00297 
00298 /* :nodoc: */
00299 static VALUE
00300 interrupt_init(int argc, VALUE *argv, VALUE self)
00301 {
00302     VALUE args[2];
00303 
00304     args[0] = INT2FIX(SIGINT);
00305     rb_scan_args(argc, argv, "01", &args[1]);
00306     return rb_call_super(2, args);
00307 }
00308 
00309 void
00310 ruby_default_signal(int sig)
00311 {
00312     signal(sig, SIG_DFL);
00313     raise(sig);
00314 }
00315 
00316 /*
00317  *  call-seq:
00318  *     Process.kill(signal, pid, ...)    -> fixnum
00319  *
00320  *  Sends the given signal to the specified process id(s), or to the
00321  *  current process if _pid_ is zero. _signal_ may be an
00322  *  integer signal number or a POSIX signal name (either with or without
00323  *  a +SIG+ prefix). If _signal_ is negative (or starts
00324  *  with a minus sign), kills process groups instead of
00325  *  processes. Not all signals are available on all platforms.
00326  *
00327  *     pid = fork do
00328  *        Signal.trap("HUP") { puts "Ouch!"; exit }
00329  *        # ... do some work ...
00330  *     end
00331  *     # ...
00332  *     Process.kill("HUP", pid)
00333  *     Process.wait
00334  *
00335  *  <em>produces:</em>
00336  *
00337  *     Ouch!
00338  *
00339  *  If _signal_ is an integer but wrong for signal,
00340  *  <code>Errno::EINVAL</code> or +RangeError+ will be raised.
00341  *  Otherwise unless _signal_ is a +String+ or a +Symbol+, and a known
00342  *  signal name, +ArgumentError+ will be raised.
00343  *
00344  *  Also, <code>Errno::ESRCH</code> or +RangeError+ for invalid _pid_,
00345  *  <code>Errno::EPERM</code> when failed because of no privilege,
00346  *  will be raised.  In these cases, signals may have been sent to
00347  *  preceding processes.
00348  */
00349 
00350 VALUE
00351 rb_f_kill(int argc, VALUE *argv)
00352 {
00353 #ifndef HAS_KILLPG
00354 #define killpg(pg, sig) kill(-(pg), (sig))
00355 #endif
00356     int negative = 0;
00357     int sig;
00358     int i;
00359     volatile VALUE str;
00360     const char *s;
00361 
00362     rb_secure(2);
00363     if (argc < 2)
00364         rb_raise(rb_eArgError, "wrong number of arguments (%d for at least 2)", argc);
00365     switch (TYPE(argv[0])) {
00366       case T_FIXNUM:
00367         sig = FIX2INT(argv[0]);
00368         break;
00369 
00370       case T_SYMBOL:
00371         s = rb_id2name(SYM2ID(argv[0]));
00372         if (!s) rb_raise(rb_eArgError, "bad signal");
00373         goto str_signal;
00374 
00375       case T_STRING:
00376         s = RSTRING_PTR(argv[0]);
00377       str_signal:
00378         if (s[0] == '-') {
00379             negative++;
00380             s++;
00381         }
00382         if (strncmp("SIG", s, 3) == 0)
00383             s += 3;
00384         if((sig = signm2signo(s)) == 0)
00385             rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
00386 
00387         if (negative)
00388             sig = -sig;
00389         break;
00390 
00391       default:
00392         str = rb_check_string_type(argv[0]);
00393         if (!NIL_P(str)) {
00394             s = RSTRING_PTR(str);
00395             goto str_signal;
00396         }
00397         rb_raise(rb_eArgError, "bad signal type %s",
00398                  rb_obj_classname(argv[0]));
00399         break;
00400     }
00401 
00402     if (sig < 0) {
00403         sig = -sig;
00404         for (i=1; i<argc; i++) {
00405             if (killpg(NUM2PIDT(argv[i]), sig) < 0)
00406                 rb_sys_fail(0);
00407         }
00408     }
00409     else {
00410         for (i=1; i<argc; i++) {
00411             if (kill(NUM2PIDT(argv[i]), sig) < 0)
00412                 rb_sys_fail(0);
00413         }
00414     }
00415     rb_thread_polling();
00416     return INT2FIX(i-1);
00417 }
00418 
00419 static struct {
00420     rb_atomic_t cnt[RUBY_NSIG];
00421     rb_atomic_t size;
00422 } signal_buff;
00423 
00424 #ifdef __dietlibc__
00425 #define sighandler_t sh_t
00426 #endif
00427 
00428 typedef RETSIGTYPE (*sighandler_t)(int);
00429 #ifdef USE_SIGALTSTACK
00430 typedef void ruby_sigaction_t(int, siginfo_t*, void*);
00431 #define SIGINFO_ARG , siginfo_t *info, void *ctx
00432 #else
00433 typedef RETSIGTYPE ruby_sigaction_t(int);
00434 #define SIGINFO_ARG
00435 #endif
00436 
00437 #ifdef POSIX_SIGNAL
00438 
00439 #ifdef USE_SIGALTSTACK
00440 /* alternate stack for SIGSEGV */
00441 void
00442 rb_register_sigaltstack(rb_thread_t *th)
00443 {
00444     stack_t newSS, oldSS;
00445 
00446     if (!th->altstack)
00447         rb_bug("rb_register_sigaltstack: th->altstack not initialized\n");
00448 
00449     newSS.ss_sp = th->altstack;
00450     newSS.ss_size = ALT_STACK_SIZE;
00451     newSS.ss_flags = 0;
00452 
00453     sigaltstack(&newSS, &oldSS); /* ignore error. */
00454 }
00455 #endif /* USE_SIGALTSTACK */
00456 
00457 static sighandler_t
00458 ruby_signal(int signum, sighandler_t handler)
00459 {
00460     struct sigaction sigact, old;
00461 
00462 #if 0
00463     rb_trap_accept_nativethreads[signum] = 0;
00464 #endif
00465 
00466     sigemptyset(&sigact.sa_mask);
00467 #ifdef USE_SIGALTSTACK
00468     sigact.sa_sigaction = (ruby_sigaction_t*)handler;
00469     sigact.sa_flags = SA_SIGINFO;
00470 #else
00471     sigact.sa_handler = handler;
00472     sigact.sa_flags = 0;
00473 #endif
00474 
00475 #ifdef SA_NOCLDWAIT
00476     if (signum == SIGCHLD && handler == SIG_IGN)
00477         sigact.sa_flags |= SA_NOCLDWAIT;
00478 #endif
00479 #if defined(SA_ONSTACK) && defined(USE_SIGALTSTACK)
00480     if (signum == SIGSEGV || signum == SIGBUS)
00481         sigact.sa_flags |= SA_ONSTACK;
00482 #endif
00483     if (sigaction(signum, &sigact, &old) < 0) {
00484         if (errno != 0 && errno != EINVAL) {
00485             rb_bug_errno("sigaction", errno);
00486         }
00487     }
00488     return old.sa_handler;
00489 }
00490 
00491 sighandler_t
00492 posix_signal(int signum, sighandler_t handler)
00493 {
00494     return ruby_signal(signum, handler);
00495 }
00496 
00497 #else /* !POSIX_SIGNAL */
00498 #define ruby_signal(sig,handler) (/* rb_trap_accept_nativethreads[(sig)] = 0,*/ signal((sig),(handler)))
00499 #if 0 /* def HAVE_NATIVETHREAD */
00500 static sighandler_t
00501 ruby_nativethread_signal(int signum, sighandler_t handler)
00502 {
00503     sighandler_t old;
00504 
00505     old = signal(signum, handler);
00506     rb_trap_accept_nativethreads[signum] = 1;
00507     return old;
00508 }
00509 #endif
00510 #endif
00511 
00512 static RETSIGTYPE
00513 sighandler(int sig)
00514 {
00515     ATOMIC_INC(signal_buff.cnt[sig]);
00516     ATOMIC_INC(signal_buff.size);
00517     rb_thread_wakeup_timer_thread();
00518 #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
00519     ruby_signal(sig, sighandler);
00520 #endif
00521 }
00522 
00523 int
00524 rb_signal_buff_size(void)
00525 {
00526     return signal_buff.size;
00527 }
00528 
00529 #if USE_TRAP_MASK
00530 static sigset_t trap_last_mask;
00531 #endif
00532 
00533 #if HAVE_PTHREAD_H
00534 #include <pthread.h>
00535 #endif
00536 
00537 void
00538 rb_disable_interrupt(void)
00539 {
00540 #if USE_TRAP_MASK
00541     sigset_t mask;
00542     sigfillset(&mask);
00543     sigdelset(&mask, SIGVTALRM);
00544     sigdelset(&mask, SIGSEGV);
00545     pthread_sigmask(SIG_SETMASK, &mask, NULL);
00546 #endif
00547 }
00548 
00549 void
00550 rb_enable_interrupt(void)
00551 {
00552 #if USE_TRAP_MASK
00553     sigset_t mask;
00554     sigemptyset(&mask);
00555     pthread_sigmask(SIG_SETMASK, &mask, NULL);
00556 #endif
00557 }
00558 
00559 int
00560 rb_get_next_signal(void)
00561 {
00562     int i, sig = 0;
00563 
00564     if (signal_buff.size != 0) {
00565         for (i=1; i<RUBY_NSIG; i++) {
00566             if (signal_buff.cnt[i] > 0) {
00567                 rb_disable_interrupt();
00568                 {
00569                     ATOMIC_DEC(signal_buff.cnt[i]);
00570                     ATOMIC_DEC(signal_buff.size);
00571                 }
00572                 rb_enable_interrupt();
00573                 sig = i;
00574                 break;
00575             }
00576         }
00577     }
00578     return sig;
00579 }
00580 
00581 
00582 #ifdef USE_SIGALTSTACK
00583 static void
00584 check_stack_overflow(const void *addr)
00585 {
00586     int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
00587     NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th));
00588     rb_thread_t *th = GET_THREAD();
00589     if (ruby_stack_overflowed_p(th, addr)) {
00590         ruby_thread_stack_overflow(th);
00591     }
00592 }
00593 #define CHECK_STACK_OVERFLOW() check_stack_overflow(info->si_addr)
00594 #else
00595 #define CHECK_STACK_OVERFLOW() (void)0
00596 #endif
00597 
00598 #ifdef SIGBUS
00599 static RETSIGTYPE
00600 sigbus(int sig SIGINFO_ARG)
00601 {
00602 /*
00603  * Mac OS X makes KERN_PROTECTION_FAILURE when thread touch guard page.
00604  * and it's delivered as SIGBUS instaed of SIGSEGV to userland. It's crazy
00605  * wrong IMHO. but anyway we have to care it. Sigh.
00606  */
00607 #if defined __APPLE__
00608     CHECK_STACK_OVERFLOW();
00609 #endif
00610     rb_bug("Bus Error");
00611 }
00612 #endif
00613 
00614 #ifdef SIGSEGV
00615 static void ruby_abort(void)
00616 {
00617 #ifdef __sun
00618     /* Solaris's abort() is async signal unsafe. Of course, it is not
00619      *  POSIX compliant.
00620      */
00621     raise(SIGABRT);
00622 #else
00623     abort();
00624 #endif
00625 
00626 }
00627 
00628 static int segv_received = 0;
00629 extern int ruby_disable_gc_stress;
00630 
00631 static RETSIGTYPE
00632 sigsegv(int sig SIGINFO_ARG)
00633 {
00634     if (segv_received) {
00635         char msg[] = "SEGV received in SEGV handler\n";
00636         write(2, msg, sizeof(msg));
00637         ruby_abort();
00638     }
00639 
00640     CHECK_STACK_OVERFLOW();
00641 
00642     segv_received = 1;
00643     ruby_disable_gc_stress = 1;
00644     rb_bug("Segmentation fault");
00645 }
00646 #endif
00647 
00648 static void
00649 signal_exec(VALUE cmd, int safe, int sig)
00650 {
00651     VALUE signum = INT2NUM(sig);
00652     rb_eval_cmd(cmd, rb_ary_new3(1, signum), safe);
00653 }
00654 
00655 void
00656 rb_trap_exit(void)
00657 {
00658     rb_vm_t *vm = GET_VM();
00659     VALUE trap_exit = vm->trap_list[0].cmd;
00660 
00661     if (trap_exit) {
00662         vm->trap_list[0].cmd = 0;
00663         signal_exec(trap_exit, vm->trap_list[0].safe, 0);
00664     }
00665 }
00666 
00667 void
00668 rb_signal_exec(rb_thread_t *th, int sig)
00669 {
00670     rb_vm_t *vm = GET_VM();
00671     VALUE cmd = vm->trap_list[sig].cmd;
00672     int safe = vm->trap_list[sig].safe;
00673 
00674     if (cmd == 0) {
00675         switch (sig) {
00676           case SIGINT:
00677             rb_interrupt();
00678             break;
00679 #ifdef SIGHUP
00680           case SIGHUP:
00681 #endif
00682 #ifdef SIGQUIT
00683           case SIGQUIT:
00684 #endif
00685 #ifdef SIGTERM
00686           case SIGTERM:
00687 #endif
00688 #ifdef SIGALRM
00689           case SIGALRM:
00690 #endif
00691 #ifdef SIGUSR1
00692           case SIGUSR1:
00693 #endif
00694 #ifdef SIGUSR2
00695           case SIGUSR2:
00696 #endif
00697             rb_threadptr_signal_raise(th, sig);
00698             break;
00699         }
00700     }
00701     else if (cmd == Qundef) {
00702         rb_threadptr_signal_exit(th);
00703     }
00704     else {
00705         signal_exec(cmd, safe, sig);
00706     }
00707 }
00708 
00709 struct trap_arg {
00710 #if USE_TRAP_MASK
00711     sigset_t mask;
00712 #endif
00713     int sig;
00714     sighandler_t func;
00715     VALUE cmd;
00716 };
00717 
00718 static sighandler_t
00719 default_handler(int sig)
00720 {
00721     sighandler_t func;
00722     switch (sig) {
00723       case SIGINT:
00724 #ifdef SIGHUP
00725       case SIGHUP:
00726 #endif
00727 #ifdef SIGQUIT
00728       case SIGQUIT:
00729 #endif
00730 #ifdef SIGTERM
00731       case SIGTERM:
00732 #endif
00733 #ifdef SIGALRM
00734       case SIGALRM:
00735 #endif
00736 #ifdef SIGUSR1
00737       case SIGUSR1:
00738 #endif
00739 #ifdef SIGUSR2
00740       case SIGUSR2:
00741 #endif
00742         func = sighandler;
00743         break;
00744 #ifdef SIGBUS
00745       case SIGBUS:
00746         func = (sighandler_t)sigbus;
00747         break;
00748 #endif
00749 #ifdef SIGSEGV
00750       case SIGSEGV:
00751         func = (sighandler_t)sigsegv;
00752 # ifdef USE_SIGALTSTACK
00753         rb_register_sigaltstack(GET_THREAD());
00754 # endif
00755         break;
00756 #endif
00757 #ifdef SIGPIPE
00758       case SIGPIPE:
00759         func = SIG_IGN;
00760         break;
00761 #endif
00762       default:
00763         func = SIG_DFL;
00764         break;
00765     }
00766 
00767     return func;
00768 }
00769 
00770 static sighandler_t
00771 trap_handler(VALUE *cmd, int sig)
00772 {
00773     sighandler_t func = sighandler;
00774     VALUE command;
00775 
00776     if (NIL_P(*cmd)) {
00777         func = SIG_IGN;
00778     }
00779     else {
00780         command = rb_check_string_type(*cmd);
00781         if (NIL_P(command) && SYMBOL_P(*cmd)) {
00782             command = rb_id2str(SYM2ID(*cmd));
00783             if (!command) rb_raise(rb_eArgError, "bad handler");
00784         }
00785         if (!NIL_P(command)) {
00786             SafeStringValue(command);   /* taint check */
00787             *cmd = command;
00788             switch (RSTRING_LEN(command)) {
00789               case 0:
00790                 goto sig_ign;
00791                 break;
00792               case 14:
00793                 if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) {
00794                     func = SIG_DFL;
00795                     *cmd = 0;
00796                 }
00797                 break;
00798               case 7:
00799                 if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) {
00800 sig_ign:
00801                     func = SIG_IGN;
00802                     *cmd = 0;
00803                 }
00804                 else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
00805 sig_dfl:
00806                     func = default_handler(sig);
00807                     *cmd = 0;
00808                 }
00809                 else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) {
00810                     goto sig_dfl;
00811                 }
00812                 break;
00813               case 6:
00814                 if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) {
00815                     goto sig_ign;
00816                 }
00817                 break;
00818               case 4:
00819                 if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) {
00820                     *cmd = Qundef;
00821                 }
00822                 break;
00823             }
00824         }
00825         else {
00826             rb_proc_t *proc;
00827             GetProcPtr(*cmd, proc);
00828         }
00829     }
00830 
00831     return func;
00832 }
00833 
00834 static int
00835 trap_signm(VALUE vsig)
00836 {
00837     int sig = -1;
00838     const char *s;
00839 
00840     switch (TYPE(vsig)) {
00841       case T_FIXNUM:
00842         sig = FIX2INT(vsig);
00843         if (sig < 0 || sig >= NSIG) {
00844             rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
00845         }
00846         break;
00847 
00848       case T_SYMBOL:
00849         s = rb_id2name(SYM2ID(vsig));
00850         if (!s) rb_raise(rb_eArgError, "bad signal");
00851         goto str_signal;
00852 
00853       default:
00854         s = StringValuePtr(vsig);
00855 
00856       str_signal:
00857         if (strncmp("SIG", s, 3) == 0)
00858             s += 3;
00859         sig = signm2signo(s);
00860         if (sig == 0 && strcmp(s, "EXIT") != 0)
00861             rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
00862     }
00863     return sig;
00864 }
00865 
00866 static VALUE
00867 trap(struct trap_arg *arg)
00868 {
00869     sighandler_t oldfunc, func = arg->func;
00870     VALUE oldcmd, command = arg->cmd;
00871     int sig = arg->sig;
00872     rb_vm_t *vm = GET_VM();
00873 
00874     oldfunc = ruby_signal(sig, func);
00875     oldcmd = vm->trap_list[sig].cmd;
00876     switch (oldcmd) {
00877       case 0:
00878         if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
00879         else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
00880         else oldcmd = Qnil;
00881         break;
00882       case Qundef:
00883         oldcmd = rb_str_new2("EXIT");
00884         break;
00885     }
00886 
00887     vm->trap_list[sig].cmd = command;
00888     vm->trap_list[sig].safe = rb_safe_level();
00889     /* enable at least specified signal. */
00890 #if USE_TRAP_MASK
00891     sigdelset(&arg->mask, sig);
00892 #endif
00893     return oldcmd;
00894 }
00895 
00896 #if USE_TRAP_MASK
00897 static VALUE
00898 trap_ensure(struct trap_arg *arg)
00899 {
00900     /* enable interrupt */
00901     pthread_sigmask(SIG_SETMASK, &arg->mask, NULL);
00902     trap_last_mask = arg->mask;
00903     return 0;
00904 }
00905 #endif
00906 
00907 void
00908 rb_trap_restore_mask(void)
00909 {
00910 #if USE_TRAP_MASK
00911     pthread_sigmask(SIG_SETMASK, &trap_last_mask, NULL);
00912 #endif
00913 }
00914 
00915 /*
00916  * call-seq:
00917  *   Signal.trap( signal, command ) -> obj
00918  *   Signal.trap( signal ) {| | block } -> obj
00919  *
00920  * Specifies the handling of signals. The first parameter is a signal
00921  * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
00922  * signal number. The characters ``SIG'' may be omitted from the
00923  * signal name. The command or block specifies code to be run when the
00924  * signal is raised.
00925  * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
00926  * will be ignored.
00927  * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
00928  * will be invoked.
00929  * If the command is ``EXIT'', the script will be terminated by the signal.
00930  * If the command is ``SYSTEM_DEFAULT'', the operating system's default
00931  * handler will be invoked.
00932  * Otherwise, the given command or block will be run.
00933  * The special signal name ``EXIT'' or signal number zero will be
00934  * invoked just prior to program termination.
00935  * trap returns the previous handler for the given signal.
00936  *
00937  *     Signal.trap(0, proc { puts "Terminating: #{$$}" })
00938  *     Signal.trap("CLD")  { puts "Child died" }
00939  *     fork && Process.wait
00940  *
00941  * produces:
00942  *     Terminating: 27461
00943  *     Child died
00944  *     Terminating: 27460
00945  */
00946 static VALUE
00947 sig_trap(int argc, VALUE *argv)
00948 {
00949     struct trap_arg arg;
00950 
00951     rb_secure(2);
00952     if (argc < 1 || argc > 2) {
00953         rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
00954     }
00955 
00956     arg.sig = trap_signm(argv[0]);
00957     if (argc == 1) {
00958         arg.cmd = rb_block_proc();
00959         arg.func = sighandler;
00960     }
00961     else {
00962         arg.cmd = argv[1];
00963         arg.func = trap_handler(&arg.cmd, arg.sig);
00964     }
00965 
00966     if (OBJ_TAINTED(arg.cmd)) {
00967         rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
00968     }
00969 #if USE_TRAP_MASK
00970     {
00971       sigset_t fullmask;
00972 
00973       /* disable interrupt */
00974       sigfillset(&fullmask);
00975       pthread_sigmask(SIG_BLOCK, &fullmask, &arg.mask);
00976 
00977       return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
00978     }
00979 #else
00980     return trap(&arg);
00981 #endif
00982 }
00983 
00984 /*
00985  * call-seq:
00986  *   Signal.list -> a_hash
00987  *
00988  * Returns a list of signal names mapped to the corresponding
00989  * underlying signal numbers.
00990  *
00991  *   Signal.list   #=> {"EXIT"=>0, "HUP"=>1, "INT"=>2, "QUIT"=>3, "ILL"=>4, "TRAP"=>5, "IOT"=>6, "ABRT"=>6, "FPE"=>8, "KILL"=>9, "BUS"=>7, "SEGV"=>11, "SYS"=>31, "PIPE"=>13, "ALRM"=>14, "TERM"=>15, "URG"=>23, "STOP"=>19, "TSTP"=>20, "CONT"=>18, "CHLD"=>17, "CLD"=>17, "TTIN"=>21, "TTOU"=>22, "IO"=>29, "XCPU"=>24, "XFSZ"=>25, "VTALRM"=>26, "PROF"=>27, "WINCH"=>28, "USR1"=>10, "USR2"=>12, "PWR"=>30, "POLL"=>29}
00992  */
00993 static VALUE
00994 sig_list(void)
00995 {
00996     VALUE h = rb_hash_new();
00997     const struct signals *sigs;
00998 
00999     for (sigs = siglist; sigs->signm; sigs++) {
01000         rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
01001     }
01002     return h;
01003 }
01004 
01005 static void
01006 install_sighandler(int signum, sighandler_t handler)
01007 {
01008     sighandler_t old;
01009 
01010     old = ruby_signal(signum, handler);
01011     if (old != SIG_DFL) {
01012         ruby_signal(signum, old);
01013     }
01014 }
01015 
01016 #if defined(SIGCLD) || defined(SIGCHLD)
01017 static void
01018 init_sigchld(int sig)
01019 {
01020     sighandler_t oldfunc;
01021 #if USE_TRAP_MASK
01022     sigset_t mask;
01023     sigset_t fullmask;
01024 
01025     /* disable interrupt */
01026     sigfillset(&fullmask);
01027     pthread_sigmask(SIG_BLOCK, &fullmask, &mask);
01028 #endif
01029 
01030     oldfunc = ruby_signal(sig, SIG_DFL);
01031     if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
01032         ruby_signal(sig, oldfunc);
01033     } else {
01034         GET_VM()->trap_list[sig].cmd = 0;
01035     }
01036 
01037 #if USE_TRAP_MASK
01038     sigdelset(&mask, sig);
01039     pthread_sigmask(SIG_SETMASK, &mask, NULL);
01040     trap_last_mask = mask;
01041 #endif
01042 }
01043 #endif
01044 
01045 void
01046 ruby_sig_finalize(void)
01047 {
01048     sighandler_t oldfunc;
01049 
01050     oldfunc = ruby_signal(SIGINT, SIG_IGN);
01051     if (oldfunc == sighandler) {
01052         ruby_signal(SIGINT, SIG_DFL);
01053     }
01054 }
01055 
01056 
01057 int ruby_enable_coredump = 0;
01058 #ifndef RUBY_DEBUG_ENV
01059 #define ruby_enable_coredump 0
01060 #endif
01061 
01062 /*
01063  * Many operating systems allow signals to be sent to running
01064  * processes. Some signals have a defined effect on the process, while
01065  * others may be trapped at the code level and acted upon. For
01066  * example, your process may trap the USR1 signal and use it to toggle
01067  * debugging, and may use TERM to initiate a controlled shutdown.
01068  *
01069  *     pid = fork do
01070  *       Signal.trap("USR1") do
01071  *         $debug = !$debug
01072  *         puts "Debug now: #$debug"
01073  *       end
01074  *       Signal.trap("TERM") do
01075  *         puts "Terminating..."
01076  *         shutdown()
01077  *       end
01078  *       # . . . do some work . . .
01079  *     end
01080  *
01081  *     Process.detach(pid)
01082  *
01083  *     # Controlling program:
01084  *     Process.kill("USR1", pid)
01085  *     # ...
01086  *     Process.kill("USR1", pid)
01087  *     # ...
01088  *     Process.kill("TERM", pid)
01089  *
01090  * produces:
01091  *     Debug now: true
01092  *     Debug now: false
01093  *    Terminating...
01094  *
01095  * The list of available signal names and their interpretation is
01096  * system dependent. Signal delivery semantics may also vary between
01097  * systems; in particular signal delivery may not always be reliable.
01098  */
01099 void
01100 Init_signal(void)
01101 {
01102     VALUE mSignal = rb_define_module("Signal");
01103 
01104     rb_define_global_function("trap", sig_trap, -1);
01105     rb_define_module_function(mSignal, "trap", sig_trap, -1);
01106     rb_define_module_function(mSignal, "list", sig_list, 0);
01107 
01108     rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
01109     rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
01110     rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
01111     rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
01112 
01113     install_sighandler(SIGINT, sighandler);
01114 #ifdef SIGHUP
01115     install_sighandler(SIGHUP, sighandler);
01116 #endif
01117 #ifdef SIGQUIT
01118     install_sighandler(SIGQUIT, sighandler);
01119 #endif
01120 #ifdef SIGTERM
01121     install_sighandler(SIGTERM, sighandler);
01122 #endif
01123 #ifdef SIGALRM
01124     install_sighandler(SIGALRM, sighandler);
01125 #endif
01126 #ifdef SIGUSR1
01127     install_sighandler(SIGUSR1, sighandler);
01128 #endif
01129 #ifdef SIGUSR2
01130     install_sighandler(SIGUSR2, sighandler);
01131 #endif
01132 
01133     if (!ruby_enable_coredump) {
01134 #ifdef SIGBUS
01135         install_sighandler(SIGBUS, (sighandler_t)sigbus);
01136 #endif
01137 #ifdef SIGSEGV
01138 # ifdef USE_SIGALTSTACK
01139         rb_register_sigaltstack(GET_THREAD());
01140 # endif
01141         install_sighandler(SIGSEGV, (sighandler_t)sigsegv);
01142 #endif
01143     }
01144 #ifdef SIGPIPE
01145     install_sighandler(SIGPIPE, SIG_IGN);
01146 #endif
01147 
01148 #if defined(SIGCLD)
01149     init_sigchld(SIGCLD);
01150 #elif defined(SIGCHLD)
01151     init_sigchld(SIGCHLD);
01152 #endif
01153 }
01154