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