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 "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)
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
00214
00215
00216
00217
00218
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
00273
00274
00275
00276
00277
00278 static VALUE
00279 esignal_signo(VALUE self)
00280 {
00281 return rb_iv_get(self, "signo");
00282 }
00283
00284
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
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 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
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);
00440 }
00441 #endif
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
00484 #define ruby_signal(sig,handler) ( signal((sig),(handler)))
00485 #if 0
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
00573
00574
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);
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
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
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
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
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
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
00952
00953
00954
00955
00956
00957
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
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
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
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