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