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 #elif defined _WIN32
00605 static inline sighandler_t
00606 ruby_signal(int signum, sighandler_t handler)
00607 {
00608 if (signum == SIGKILL) {
00609 errno = EINVAL;
00610 return SIG_ERR;
00611 }
00612 return signal(signum, handler);
00613 }
00614
00615 #else
00616 #define ruby_signal(sig,handler) ( signal((sig),(handler)))
00617 #if 0
00618 static sighandler_t
00619 ruby_nativethread_signal(int signum, sighandler_t handler)
00620 {
00621 sighandler_t old;
00622
00623 old = signal(signum, handler);
00624 rb_trap_accept_nativethreads[signum] = 1;
00625 return old;
00626 }
00627 #endif
00628 #endif
00629
00630 static int
00631 signal_ignored(int sig)
00632 {
00633 sighandler_t func;
00634 #ifdef POSIX_SIGNAL
00635 struct sigaction old;
00636 (void)VALGRIND_MAKE_MEM_DEFINED(&old, sizeof(old));
00637 if (sigaction(sig, NULL, &old) < 0) return FALSE;
00638 func = old.sa_handler;
00639 #else
00640 sighandler_t old = signal(sig, SIG_DFL);
00641 signal(sig, old);
00642 func = old;
00643 #endif
00644 if (func == SIG_IGN) return 1;
00645 return func == sighandler ? 0 : -1;
00646 }
00647
00648 static void
00649 signal_enque(int sig)
00650 {
00651 ATOMIC_INC(signal_buff.cnt[sig]);
00652 ATOMIC_INC(signal_buff.size);
00653 }
00654
00655 static RETSIGTYPE
00656 sighandler(int sig)
00657 {
00658 signal_enque(sig);
00659 rb_thread_wakeup_timer_thread();
00660 #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
00661 ruby_signal(sig, sighandler);
00662 #endif
00663 }
00664
00665 int
00666 rb_signal_buff_size(void)
00667 {
00668 return signal_buff.size;
00669 }
00670
00671 #if HAVE_PTHREAD_H
00672 #include <pthread.h>
00673 #endif
00674
00675 static void
00676 rb_disable_interrupt(void)
00677 {
00678 #ifdef HAVE_PTHREAD_SIGMASK
00679 sigset_t mask;
00680 sigfillset(&mask);
00681 pthread_sigmask(SIG_SETMASK, &mask, NULL);
00682 #endif
00683 }
00684
00685 static void
00686 rb_enable_interrupt(void)
00687 {
00688 #ifdef HAVE_PTHREAD_SIGMASK
00689 sigset_t mask;
00690 sigemptyset(&mask);
00691 pthread_sigmask(SIG_SETMASK, &mask, NULL);
00692 #endif
00693 }
00694
00695 int
00696 rb_get_next_signal(void)
00697 {
00698 int i, sig = 0;
00699
00700 if (signal_buff.size != 0) {
00701 for (i=1; i<RUBY_NSIG; i++) {
00702 if (signal_buff.cnt[i] > 0) {
00703 ATOMIC_DEC(signal_buff.cnt[i]);
00704 ATOMIC_DEC(signal_buff.size);
00705 sig = i;
00706 break;
00707 }
00708 }
00709 }
00710 return sig;
00711 }
00712
00713
00714 #if defined(USE_SIGALTSTACK) || defined(_WIN32)
00715 NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th));
00716 #if defined(HAVE_UCONTEXT_H) && defined __linux__ && (defined __i386__ || defined __x86_64__)
00717 # define USE_UCONTEXT_REG 1
00718 #endif
00719 #ifdef USE_UCONTEXT_REG
00720 static void
00721 check_stack_overflow(const uintptr_t addr, const ucontext_t *ctx)
00722 {
00723 # if defined REG_RSP
00724 const greg_t sp = ctx->uc_mcontext.gregs[REG_RSP];
00725 # else
00726 const greg_t sp = ctx->uc_mcontext.gregs[REG_ESP];
00727 # endif
00728 enum {pagesize = 4096};
00729 const uintptr_t sp_page = (uintptr_t)sp / pagesize;
00730 const uintptr_t fault_page = addr / pagesize;
00731
00732
00733
00734 if (sp_page == fault_page || sp_page == fault_page + 1) {
00735 rb_thread_t *th = ruby_current_thread;
00736 if ((uintptr_t)th->tag->buf / pagesize == sp_page) {
00737
00738
00739
00740 th->tag = th->tag->prev;
00741 }
00742 ruby_thread_stack_overflow(th);
00743 }
00744 }
00745 #else
00746 static void
00747 check_stack_overflow(const void *addr)
00748 {
00749 int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
00750 rb_thread_t *th = ruby_current_thread;
00751 if (ruby_stack_overflowed_p(th, addr)) {
00752 ruby_thread_stack_overflow(th);
00753 }
00754 }
00755 #endif
00756 #ifdef _WIN32
00757 #define CHECK_STACK_OVERFLOW() check_stack_overflow(0)
00758 #else
00759 #define FAULT_ADDRESS info->si_addr
00760 # ifdef USE_UCONTEXT_REG
00761 # define CHECK_STACK_OVERFLOW() check_stack_overflow((uintptr_t)FAULT_ADDRESS, ctx)
00762 #else
00763 # define CHECK_STACK_OVERFLOW() check_stack_overflow(FAULT_ADDRESS)
00764 #endif
00765 #define MESSAGE_FAULT_ADDRESS " at %p", FAULT_ADDRESS
00766 #endif
00767 #else
00768 #define CHECK_STACK_OVERFLOW() (void)0
00769 #endif
00770 #ifndef MESSAGE_FAULT_ADDRESS
00771 #define MESSAGE_FAULT_ADDRESS
00772 #endif
00773
00774 #ifdef SIGBUS
00775 static RETSIGTYPE
00776 sigbus(int sig SIGINFO_ARG)
00777 {
00778
00779
00780
00781
00782
00783
00784 #if defined __APPLE__ || defined __linux__
00785 CHECK_STACK_OVERFLOW();
00786 #endif
00787 rb_bug("Bus Error" MESSAGE_FAULT_ADDRESS);
00788 }
00789 #endif
00790
00791 #ifdef SIGSEGV
00792 static void
00793 ruby_abort(void)
00794 {
00795 #ifdef __sun
00796
00797
00798
00799 raise(SIGABRT);
00800 #else
00801 abort();
00802 #endif
00803
00804 }
00805
00806 static int segv_received = 0;
00807 extern int ruby_disable_gc_stress;
00808
00809 static RETSIGTYPE
00810 sigsegv(int sig SIGINFO_ARG)
00811 {
00812 if (segv_received) {
00813 ssize_t RB_UNUSED_VAR(err);
00814 char msg[] = "SEGV received in SEGV handler\n";
00815
00816 err = write(2, msg, sizeof(msg));
00817 ruby_abort();
00818 }
00819
00820 CHECK_STACK_OVERFLOW();
00821
00822 segv_received = 1;
00823 ruby_disable_gc_stress = 1;
00824 rb_bug("Segmentation fault" MESSAGE_FAULT_ADDRESS);
00825 }
00826 #endif
00827
00828 static void
00829 signal_exec(VALUE cmd, int safe, int sig)
00830 {
00831 rb_thread_t *cur_th = GET_THREAD();
00832 volatile unsigned long old_interrupt_mask = cur_th->interrupt_mask;
00833 int state;
00834
00835
00836
00837
00838
00839
00840
00841 if (IMMEDIATE_P(cmd))
00842 return;
00843
00844 cur_th->interrupt_mask |= TRAP_INTERRUPT_MASK;
00845 TH_PUSH_TAG(cur_th);
00846 if ((state = EXEC_TAG()) == 0) {
00847 VALUE signum = INT2NUM(sig);
00848 rb_eval_cmd(cmd, rb_ary_new3(1, signum), safe);
00849 }
00850 TH_POP_TAG();
00851 cur_th = GET_THREAD();
00852 cur_th->interrupt_mask = old_interrupt_mask;
00853
00854 if (state) {
00855
00856 JUMP_TAG(state);
00857 }
00858 }
00859
00860 void
00861 rb_trap_exit(void)
00862 {
00863 rb_vm_t *vm = GET_VM();
00864 VALUE trap_exit = vm->trap_list[0].cmd;
00865
00866 if (trap_exit) {
00867 vm->trap_list[0].cmd = 0;
00868 signal_exec(trap_exit, vm->trap_list[0].safe, 0);
00869 }
00870 }
00871
00872 void
00873 rb_signal_exec(rb_thread_t *th, int sig)
00874 {
00875 rb_vm_t *vm = GET_VM();
00876 VALUE cmd = vm->trap_list[sig].cmd;
00877 int safe = vm->trap_list[sig].safe;
00878
00879 if (cmd == 0) {
00880 switch (sig) {
00881 case SIGINT:
00882 rb_interrupt();
00883 break;
00884 #ifdef SIGHUP
00885 case SIGHUP:
00886 #endif
00887 #ifdef SIGQUIT
00888 case SIGQUIT:
00889 #endif
00890 #ifdef SIGTERM
00891 case SIGTERM:
00892 #endif
00893 #ifdef SIGALRM
00894 case SIGALRM:
00895 #endif
00896 #ifdef SIGUSR1
00897 case SIGUSR1:
00898 #endif
00899 #ifdef SIGUSR2
00900 case SIGUSR2:
00901 #endif
00902 rb_threadptr_signal_raise(th, sig);
00903 break;
00904 }
00905 }
00906 else if (cmd == Qundef) {
00907 rb_threadptr_signal_exit(th);
00908 }
00909 else {
00910 signal_exec(cmd, safe, sig);
00911 }
00912 }
00913
00914 static sighandler_t
00915 default_handler(int sig)
00916 {
00917 sighandler_t func;
00918 switch (sig) {
00919 case SIGINT:
00920 #ifdef SIGHUP
00921 case SIGHUP:
00922 #endif
00923 #ifdef SIGQUIT
00924 case SIGQUIT:
00925 #endif
00926 #ifdef SIGTERM
00927 case SIGTERM:
00928 #endif
00929 #ifdef SIGALRM
00930 case SIGALRM:
00931 #endif
00932 #ifdef SIGUSR1
00933 case SIGUSR1:
00934 #endif
00935 #ifdef SIGUSR2
00936 case SIGUSR2:
00937 #endif
00938 func = sighandler;
00939 break;
00940 #ifdef SIGBUS
00941 case SIGBUS:
00942 func = (sighandler_t)sigbus;
00943 break;
00944 #endif
00945 #ifdef SIGSEGV
00946 case SIGSEGV:
00947 func = (sighandler_t)sigsegv;
00948 break;
00949 #endif
00950 #ifdef SIGPIPE
00951 case SIGPIPE:
00952 func = SIG_IGN;
00953 break;
00954 #endif
00955 default:
00956 func = SIG_DFL;
00957 break;
00958 }
00959
00960 return func;
00961 }
00962
00963 static sighandler_t
00964 trap_handler(VALUE *cmd, int sig)
00965 {
00966 sighandler_t func = sighandler;
00967 VALUE command;
00968
00969 if (NIL_P(*cmd)) {
00970 func = SIG_IGN;
00971 }
00972 else {
00973 command = rb_check_string_type(*cmd);
00974 if (NIL_P(command) && SYMBOL_P(*cmd)) {
00975 command = rb_id2str(SYM2ID(*cmd));
00976 if (!command) rb_raise(rb_eArgError, "bad handler");
00977 }
00978 if (!NIL_P(command)) {
00979 SafeStringValue(command);
00980 *cmd = command;
00981 switch (RSTRING_LEN(command)) {
00982 case 0:
00983 goto sig_ign;
00984 break;
00985 case 14:
00986 if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) {
00987 func = SIG_DFL;
00988 *cmd = 0;
00989 }
00990 break;
00991 case 7:
00992 if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) {
00993 sig_ign:
00994 func = SIG_IGN;
00995 *cmd = Qtrue;
00996 }
00997 else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
00998 sig_dfl:
00999 func = default_handler(sig);
01000 *cmd = 0;
01001 }
01002 else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) {
01003 goto sig_dfl;
01004 }
01005 break;
01006 case 6:
01007 if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) {
01008 goto sig_ign;
01009 }
01010 break;
01011 case 4:
01012 if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) {
01013 *cmd = Qundef;
01014 }
01015 break;
01016 }
01017 }
01018 else {
01019 rb_proc_t *proc;
01020 GetProcPtr(*cmd, proc);
01021 (void)proc;
01022 }
01023 }
01024
01025 return func;
01026 }
01027
01028 static int
01029 trap_signm(VALUE vsig)
01030 {
01031 int sig = -1;
01032 const char *s;
01033
01034 switch (TYPE(vsig)) {
01035 case T_FIXNUM:
01036 sig = FIX2INT(vsig);
01037 if (sig < 0 || sig >= NSIG) {
01038 rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
01039 }
01040 break;
01041
01042 case T_SYMBOL:
01043 s = rb_id2name(SYM2ID(vsig));
01044 if (!s) rb_raise(rb_eArgError, "bad signal");
01045 goto str_signal;
01046
01047 default:
01048 s = StringValuePtr(vsig);
01049
01050 str_signal:
01051 if (strncmp("SIG", s, 3) == 0)
01052 s += 3;
01053 sig = signm2signo(s);
01054 if (sig == 0 && strcmp(s, "EXIT") != 0)
01055 rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
01056 }
01057 return sig;
01058 }
01059
01060 static VALUE
01061 trap(int sig, sighandler_t func, VALUE command)
01062 {
01063 sighandler_t oldfunc;
01064 VALUE oldcmd;
01065 rb_vm_t *vm = GET_VM();
01066
01067
01068
01069
01070
01071
01072 oldfunc = ruby_signal(sig, func);
01073 oldcmd = vm->trap_list[sig].cmd;
01074 switch (oldcmd) {
01075 case 0:
01076 case Qtrue:
01077 if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
01078 else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
01079 else oldcmd = Qnil;
01080 break;
01081 case Qnil:
01082 break;
01083 case Qundef:
01084 oldcmd = rb_str_new2("EXIT");
01085 break;
01086 }
01087
01088 vm->trap_list[sig].cmd = command;
01089 vm->trap_list[sig].safe = rb_safe_level();
01090
01091 return oldcmd;
01092 }
01093
01094 static int
01095 reserved_signal_p(int signo)
01096 {
01097
01098 #ifdef SIGSEGV
01099 if (signo == SIGSEGV)
01100 return 1;
01101 #endif
01102 #ifdef SIGBUS
01103 if (signo == SIGBUS)
01104 return 1;
01105 #endif
01106 #ifdef SIGILL
01107 if (signo == SIGILL)
01108 return 1;
01109 #endif
01110 #ifdef SIGFPE
01111 if (signo == SIGFPE)
01112 return 1;
01113 #endif
01114
01115
01116 #ifdef SIGVTALRM
01117 if (signo == SIGVTALRM)
01118 return 1;
01119 #endif
01120
01121 return 0;
01122 }
01123
01124
01125
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 static VALUE
01156 sig_trap(int argc, VALUE *argv)
01157 {
01158 int sig;
01159 sighandler_t func;
01160 VALUE cmd;
01161
01162 rb_secure(2);
01163 rb_check_arity(argc, 1, 2);
01164
01165 sig = trap_signm(argv[0]);
01166 if (reserved_signal_p(sig)) {
01167 const char *name = signo2signm(sig);
01168 if (name)
01169 rb_raise(rb_eArgError, "can't trap reserved signal: SIG%s", name);
01170 else
01171 rb_raise(rb_eArgError, "can't trap reserved signal: %d", sig);
01172 }
01173
01174 if (argc == 1) {
01175 cmd = rb_block_proc();
01176 func = sighandler;
01177 }
01178 else {
01179 cmd = argv[1];
01180 func = trap_handler(&cmd, sig);
01181 }
01182
01183 if (OBJ_TAINTED(cmd)) {
01184 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
01185 }
01186
01187 return trap(sig, func, cmd);
01188 }
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199 static VALUE
01200 sig_list(void)
01201 {
01202 VALUE h = rb_hash_new();
01203 const struct signals *sigs;
01204
01205 for (sigs = siglist; sigs->signm; sigs++) {
01206 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
01207 }
01208 return h;
01209 }
01210
01211 static void
01212 install_sighandler(int signum, sighandler_t handler)
01213 {
01214 sighandler_t old;
01215
01216
01217 rb_disable_interrupt();
01218 old = ruby_signal(signum, handler);
01219
01220 if (old != SIG_DFL) {
01221 ruby_signal(signum, old);
01222 }
01223 rb_enable_interrupt();
01224 }
01225
01226 #if defined(SIGCLD) || defined(SIGCHLD)
01227 static void
01228 init_sigchld(int sig)
01229 {
01230 sighandler_t oldfunc;
01231
01232 rb_disable_interrupt();
01233 oldfunc = ruby_signal(sig, SIG_DFL);
01234 if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
01235 ruby_signal(sig, oldfunc);
01236 } else {
01237 GET_VM()->trap_list[sig].cmd = 0;
01238 }
01239 rb_enable_interrupt();
01240 }
01241 #endif
01242
01243 void
01244 ruby_sig_finalize(void)
01245 {
01246 sighandler_t oldfunc;
01247
01248 oldfunc = ruby_signal(SIGINT, SIG_IGN);
01249 if (oldfunc == sighandler) {
01250 ruby_signal(SIGINT, SIG_DFL);
01251 }
01252 }
01253
01254
01255 int ruby_enable_coredump = 0;
01256 #ifndef RUBY_DEBUG_ENV
01257 #define ruby_enable_coredump 0
01258 #endif
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
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297 void
01298 Init_signal(void)
01299 {
01300 VALUE mSignal = rb_define_module("Signal");
01301
01302 rb_define_global_function("trap", sig_trap, -1);
01303 rb_define_module_function(mSignal, "trap", sig_trap, -1);
01304 rb_define_module_function(mSignal, "list", sig_list, 0);
01305 rb_define_module_function(mSignal, "signame", sig_signame, 1);
01306
01307 rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
01308 rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
01309 rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
01310 rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
01311
01312 install_sighandler(SIGINT, sighandler);
01313 #ifdef SIGHUP
01314 install_sighandler(SIGHUP, sighandler);
01315 #endif
01316 #ifdef SIGQUIT
01317 install_sighandler(SIGQUIT, sighandler);
01318 #endif
01319 #ifdef SIGTERM
01320 install_sighandler(SIGTERM, sighandler);
01321 #endif
01322 #ifdef SIGALRM
01323 install_sighandler(SIGALRM, sighandler);
01324 #endif
01325 #ifdef SIGUSR1
01326 install_sighandler(SIGUSR1, sighandler);
01327 #endif
01328 #ifdef SIGUSR2
01329 install_sighandler(SIGUSR2, sighandler);
01330 #endif
01331
01332 if (!ruby_enable_coredump) {
01333 #ifdef SIGBUS
01334 install_sighandler(SIGBUS, (sighandler_t)sigbus);
01335 #endif
01336 #ifdef SIGSEGV
01337 # ifdef USE_SIGALTSTACK
01338 rb_register_sigaltstack(GET_THREAD());
01339 # endif
01340 install_sighandler(SIGSEGV, (sighandler_t)sigsegv);
01341 #endif
01342 }
01343 #ifdef SIGPIPE
01344 install_sighandler(SIGPIPE, SIG_IGN);
01345 #endif
01346
01347 #if defined(SIGCLD)
01348 init_sigchld(SIGCLD);
01349 #elif defined(SIGCHLD)
01350 init_sigchld(SIGCHLD);
01351 #endif
01352 }
01353