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