Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# signal.c

Go to the documentation of this file.

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