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