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 #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)
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
00217
00218
00219
00220
00221
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
00276
00277
00278
00279
00280
00281 static VALUE
00282 esignal_signo(VALUE self)
00283 {
00284 return rb_iv_get(self, "signo");
00285 }
00286
00287
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
00307
00308
00309
00310
00311
00312
00313
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 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
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);
00443 }
00444 #endif
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
00487 #define ruby_signal(sig,handler) ( signal((sig),(handler)))
00488 #if 0
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
00593
00594
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
00608
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);
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
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
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
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
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
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
00975
00976
00977
00978
00979
00980
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
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
01053
01054
01055
01056
01057
01058
01059
01060
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 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