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