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
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)
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
00220
00221
00222
00223
00224
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
00279
00280
00281
00282
00283
00284 static VALUE
00285 esignal_signo(VALUE self)
00286 {
00287 return rb_iv_get(self, "signo");
00288 }
00289
00290
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
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
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
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
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);
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
00500 #define ruby_signal(sig,handler) ( signal((sig),(handler)))
00501 #if 0
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 if (signal_buff.size != 0) {
00570 for (i=1; i<RUBY_NSIG; i++) {
00571 if (signal_buff.cnt[i] > 0) {
00572 rb_disable_interrupt();
00573 {
00574 ATOMIC_DEC(signal_buff.cnt[i]);
00575 ATOMIC_DEC(signal_buff.size);
00576 }
00577 rb_enable_interrupt();
00578 sig = i;
00579 break;
00580 }
00581 }
00582 }
00583 return sig;
00584 }
00585
00586 #ifdef SIGBUS
00587 static RETSIGTYPE
00588 sigbus(int sig)
00589 {
00590 rb_bug("Bus Error");
00591 }
00592 #endif
00593
00594 #ifdef SIGSEGV
00595 static int segv_received = 0;
00596 static RETSIGTYPE
00597 sigsegv(int sig SIGINFO_ARG)
00598 {
00599 #ifdef USE_SIGALTSTACK
00600 int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
00601 NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th));
00602 rb_thread_t *th = GET_THREAD();
00603 if (ruby_stack_overflowed_p(th, info->si_addr)) {
00604 ruby_thread_stack_overflow(th);
00605 }
00606 #endif
00607 if (segv_received) {
00608 fprintf(stderr, "SEGV received in SEGV handler\n");
00609 exit(EXIT_FAILURE);
00610 }
00611 else {
00612 extern int ruby_disable_gc_stress;
00613 segv_received = 1;
00614 ruby_disable_gc_stress = 1;
00615 rb_bug("Segmentation fault");
00616 }
00617 }
00618 #endif
00619
00620 #ifdef SIGPIPE
00621 static RETSIGTYPE
00622 sigpipe(int sig)
00623 {
00624
00625 }
00626 #endif
00627
00628 static void
00629 signal_exec(VALUE cmd, int safe, int sig)
00630 {
00631 VALUE signum = INT2NUM(sig);
00632 rb_eval_cmd(cmd, rb_ary_new3(1, signum), safe);
00633 }
00634
00635 void
00636 rb_trap_exit(void)
00637 {
00638 rb_vm_t *vm = GET_VM();
00639 VALUE trap_exit = vm->trap_list[0].cmd;
00640
00641 if (trap_exit) {
00642 vm->trap_list[0].cmd = 0;
00643 signal_exec(trap_exit, vm->trap_list[0].safe, 0);
00644 }
00645 }
00646
00647 void
00648 rb_signal_exec(rb_thread_t *th, int sig)
00649 {
00650 rb_vm_t *vm = GET_VM();
00651 VALUE cmd = vm->trap_list[sig].cmd;
00652 int safe = vm->trap_list[sig].safe;
00653
00654 if (cmd == 0) {
00655 switch (sig) {
00656 case SIGINT:
00657 rb_interrupt();
00658 break;
00659 #ifdef SIGHUP
00660 case SIGHUP:
00661 #endif
00662 #ifdef SIGQUIT
00663 case SIGQUIT:
00664 #endif
00665 #ifdef SIGTERM
00666 case SIGTERM:
00667 #endif
00668 #ifdef SIGALRM
00669 case SIGALRM:
00670 #endif
00671 #ifdef SIGUSR1
00672 case SIGUSR1:
00673 #endif
00674 #ifdef SIGUSR2
00675 case SIGUSR2:
00676 #endif
00677 rb_threadptr_signal_raise(th, sig);
00678 break;
00679 }
00680 }
00681 else if (cmd == Qundef) {
00682 rb_threadptr_signal_exit(th);
00683 }
00684 else {
00685 signal_exec(cmd, safe, sig);
00686 }
00687 }
00688
00689 struct trap_arg {
00690 #if USE_TRAP_MASK
00691 # ifdef HAVE_SIGPROCMASK
00692 sigset_t mask;
00693 # else
00694 int mask;
00695 # endif
00696 #endif
00697 int sig;
00698 sighandler_t func;
00699 VALUE cmd;
00700 };
00701
00702 static sighandler_t
00703 default_handler(int sig)
00704 {
00705 sighandler_t func;
00706 switch (sig) {
00707 case SIGINT:
00708 #ifdef SIGHUP
00709 case SIGHUP:
00710 #endif
00711 #ifdef SIGQUIT
00712 case SIGQUIT:
00713 #endif
00714 #ifdef SIGTERM
00715 case SIGTERM:
00716 #endif
00717 #ifdef SIGALRM
00718 case SIGALRM:
00719 #endif
00720 #ifdef SIGUSR1
00721 case SIGUSR1:
00722 #endif
00723 #ifdef SIGUSR2
00724 case SIGUSR2:
00725 #endif
00726 func = sighandler;
00727 break;
00728 #ifdef SIGBUS
00729 case SIGBUS:
00730 func = sigbus;
00731 break;
00732 #endif
00733 #ifdef SIGSEGV
00734 case SIGSEGV:
00735 func = (sighandler_t)sigsegv;
00736 # ifdef USE_SIGALTSTACK
00737 rb_register_sigaltstack(GET_THREAD());
00738 # endif
00739 break;
00740 #endif
00741 #ifdef SIGPIPE
00742 case SIGPIPE:
00743 func = sigpipe;
00744 break;
00745 #endif
00746 default:
00747 func = SIG_DFL;
00748 break;
00749 }
00750
00751 return func;
00752 }
00753
00754 static sighandler_t
00755 trap_handler(VALUE *cmd, int sig)
00756 {
00757 sighandler_t func = sighandler;
00758 VALUE command;
00759
00760 if (NIL_P(*cmd)) {
00761 func = SIG_IGN;
00762 }
00763 else {
00764 command = rb_check_string_type(*cmd);
00765 if (NIL_P(command) && SYMBOL_P(*cmd)) {
00766 command = rb_id2str(SYM2ID(*cmd));
00767 if (!command) rb_raise(rb_eArgError, "bad handler");
00768 }
00769 if (!NIL_P(command)) {
00770 SafeStringValue(command);
00771 *cmd = command;
00772 switch (RSTRING_LEN(command)) {
00773 case 0:
00774 goto sig_ign;
00775 break;
00776 case 14:
00777 if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) {
00778 func = SIG_DFL;
00779 *cmd = 0;
00780 }
00781 break;
00782 case 7:
00783 if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) {
00784 sig_ign:
00785 func = SIG_IGN;
00786 *cmd = 0;
00787 }
00788 else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
00789 sig_dfl:
00790 func = default_handler(sig);
00791 *cmd = 0;
00792 }
00793 else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) {
00794 goto sig_dfl;
00795 }
00796 break;
00797 case 6:
00798 if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) {
00799 goto sig_ign;
00800 }
00801 break;
00802 case 4:
00803 if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) {
00804 *cmd = Qundef;
00805 }
00806 break;
00807 }
00808 }
00809 else {
00810 rb_proc_t *proc;
00811 GetProcPtr(*cmd, proc);
00812 }
00813 }
00814
00815 return func;
00816 }
00817
00818 static int
00819 trap_signm(VALUE vsig)
00820 {
00821 int sig = -1;
00822 const char *s;
00823
00824 switch (TYPE(vsig)) {
00825 case T_FIXNUM:
00826 sig = FIX2INT(vsig);
00827 if (sig < 0 || sig >= NSIG) {
00828 rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
00829 }
00830 break;
00831
00832 case T_SYMBOL:
00833 s = rb_id2name(SYM2ID(vsig));
00834 if (!s) rb_raise(rb_eArgError, "bad signal");
00835 goto str_signal;
00836
00837 default:
00838 s = StringValuePtr(vsig);
00839
00840 str_signal:
00841 if (strncmp("SIG", s, 3) == 0)
00842 s += 3;
00843 sig = signm2signo(s);
00844 if (sig == 0 && strcmp(s, "EXIT") != 0)
00845 rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
00846 }
00847 return sig;
00848 }
00849
00850 static VALUE
00851 trap(struct trap_arg *arg)
00852 {
00853 sighandler_t oldfunc, func = arg->func;
00854 VALUE oldcmd, command = arg->cmd;
00855 int sig = arg->sig;
00856 rb_vm_t *vm = GET_VM();
00857
00858 oldfunc = ruby_signal(sig, func);
00859 oldcmd = vm->trap_list[sig].cmd;
00860 switch (oldcmd) {
00861 case 0:
00862 if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
00863 else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
00864 else oldcmd = Qnil;
00865 break;
00866 case Qundef:
00867 oldcmd = rb_str_new2("EXIT");
00868 break;
00869 }
00870
00871 vm->trap_list[sig].cmd = command;
00872 vm->trap_list[sig].safe = rb_safe_level();
00873
00874 #if USE_TRAP_MASK
00875 #ifdef HAVE_SIGPROCMASK
00876 sigdelset(&arg->mask, sig);
00877 #else
00878 arg->mask &= ~sigmask(sig);
00879 #endif
00880 #endif
00881 return oldcmd;
00882 }
00883
00884 #if USE_TRAP_MASK
00885 static VALUE
00886 trap_ensure(struct trap_arg *arg)
00887 {
00888
00889 pthread_sigmask(SIG_SETMASK, &arg->mask, NULL);
00890 trap_last_mask = arg->mask;
00891 return 0;
00892 }
00893 #endif
00894
00895 void
00896 rb_trap_restore_mask(void)
00897 {
00898 #if USE_TRAP_MASK
00899 pthread_sigmask(SIG_SETMASK, &trap_last_mask, NULL);
00900 #endif
00901 }
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 static VALUE
00935 sig_trap(int argc, VALUE *argv)
00936 {
00937 struct trap_arg arg;
00938
00939 rb_secure(2);
00940 if (argc < 1 || argc > 2) {
00941 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
00942 }
00943
00944 arg.sig = trap_signm(argv[0]);
00945 if (argc == 1) {
00946 arg.cmd = rb_block_proc();
00947 arg.func = sighandler;
00948 }
00949 else {
00950 arg.cmd = argv[1];
00951 arg.func = trap_handler(&arg.cmd, arg.sig);
00952 }
00953
00954 if (OBJ_TAINTED(arg.cmd)) {
00955 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
00956 }
00957 #if USE_TRAP_MASK
00958 {
00959 sigset_t fullmask;
00960
00961
00962 sigfillset(&fullmask);
00963 pthread_sigmask(SIG_BLOCK, &fullmask, &arg.mask);
00964
00965 return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
00966 }
00967 #else
00968 return trap(&arg);
00969 #endif
00970 }
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 static VALUE
00982 sig_list(void)
00983 {
00984 VALUE h = rb_hash_new();
00985 const struct signals *sigs;
00986
00987 for (sigs = siglist; sigs->signm; sigs++) {
00988 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
00989 }
00990 return h;
00991 }
00992
00993 static void
00994 install_sighandler(int signum, sighandler_t handler)
00995 {
00996 sighandler_t old;
00997
00998 old = ruby_signal(signum, handler);
00999 if (old != SIG_DFL) {
01000 ruby_signal(signum, old);
01001 }
01002 }
01003
01004 #if defined(SIGCLD) || defined(SIGCHLD)
01005 static void
01006 init_sigchld(int sig)
01007 {
01008 sighandler_t oldfunc;
01009 #if USE_TRAP_MASK
01010 # ifdef HAVE_SIGPROCMASK
01011 sigset_t mask;
01012 sigset_t fullmask;
01013 # else
01014 int mask;
01015 int fullmask;
01016 # endif
01017 #endif
01018
01019 #if USE_TRAP_MASK
01020
01021 sigfillset(&fullmask);
01022 pthread_sigmask(SIG_BLOCK, &fullmask, &mask);
01023 #endif
01024
01025 oldfunc = ruby_signal(sig, SIG_DFL);
01026 if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
01027 ruby_signal(sig, oldfunc);
01028 } else {
01029 GET_VM()->trap_list[sig].cmd = 0;
01030 }
01031
01032 #if USE_TRAP_MASK
01033 sigdelset(&mask, sig);
01034 pthread_sigmask(SIG_SETMASK, &mask, NULL);
01035 trap_last_mask = mask;
01036 #endif
01037 }
01038 #endif
01039
01040 void
01041 ruby_sig_finalize(void)
01042 {
01043 sighandler_t oldfunc;
01044
01045 oldfunc = ruby_signal(SIGINT, SIG_IGN);
01046 if (oldfunc == sighandler) {
01047 ruby_signal(SIGINT, SIG_DFL);
01048 }
01049 }
01050
01051
01052 #ifdef RUBY_DEBUG_ENV
01053 int ruby_enable_coredump = 0;
01054 #endif
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
01089
01090
01091
01092
01093 void
01094 Init_signal(void)
01095 {
01096 VALUE mSignal = rb_define_module("Signal");
01097
01098 rb_define_global_function("trap", sig_trap, -1);
01099 rb_define_module_function(mSignal, "trap", sig_trap, -1);
01100 rb_define_module_function(mSignal, "list", sig_list, 0);
01101
01102 rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
01103 rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
01104 rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
01105 rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
01106
01107 install_sighandler(SIGINT, sighandler);
01108 #ifdef SIGHUP
01109 install_sighandler(SIGHUP, sighandler);
01110 #endif
01111 #ifdef SIGQUIT
01112 install_sighandler(SIGQUIT, sighandler);
01113 #endif
01114 #ifdef SIGTERM
01115 install_sighandler(SIGTERM, sighandler);
01116 #endif
01117 #ifdef SIGALRM
01118 install_sighandler(SIGALRM, sighandler);
01119 #endif
01120 #ifdef SIGUSR1
01121 install_sighandler(SIGUSR1, sighandler);
01122 #endif
01123 #ifdef SIGUSR2
01124 install_sighandler(SIGUSR2, sighandler);
01125 #endif
01126
01127 #ifdef RUBY_DEBUG_ENV
01128 if (!ruby_enable_coredump)
01129 #endif
01130 {
01131 #ifdef SIGBUS
01132 install_sighandler(SIGBUS, sigbus);
01133 #endif
01134 #ifdef SIGSEGV
01135 # ifdef USE_SIGALTSTACK
01136 rb_register_sigaltstack(GET_THREAD());
01137 # endif
01138 install_sighandler(SIGSEGV, (sighandler_t)sigsegv);
01139 #endif
01140 }
01141 #ifdef SIGPIPE
01142 install_sighandler(SIGPIPE, sigpipe);
01143 #endif
01144
01145 #if defined(SIGCLD)
01146 init_sigchld(SIGCLD);
01147 #elif defined(SIGCHLD)
01148 init_sigchld(SIGCHLD);
01149 #endif
01150 }
01151