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