|
Ruby
1.9.3p537(2014-02-19revision0)
|
00001 /********************************************************************** 00002 00003 signal.c - 00004 00005 $Author$ 00006 created at: Tue Dec 20 10:13:44 JST 1994 00007 00008 Copyright (C) 1993-2007 Yukihiro Matsumoto 00009 Copyright (C) 2000 Network Applied Communication Laboratory, Inc. 00010 Copyright (C) 2000 Information-technology Promotion Agency, Japan 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 #ifdef HAVE_UNISTD_H 00021 # include <unistd.h> 00022 #endif 00023 00024 #if !defined(_WIN32) && !defined(HAVE_GCC_ATOMIC_BUILTINS) 00025 rb_atomic_t 00026 ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val) 00027 { 00028 rb_atomic_t old = *ptr; 00029 *ptr = val; 00030 return old; 00031 } 00032 00033 rb_atomic_t 00034 ruby_atomic_compare_and_swap(rb_atomic_t *ptr, rb_atomic_t cmp, 00035 rb_atomic_t newval) 00036 { 00037 rb_atomic_t old = *ptr; 00038 if (old == cmp) { 00039 *ptr = newval; 00040 } 00041 return old; 00042 } 00043 #endif 00044 00045 #if defined(__BEOS__) || defined(__HAIKU__) 00046 #undef SIGBUS 00047 #endif 00048 00049 #ifdef HAVE_PTHREAD_SIGMASK 00050 #define USE_TRAP_MASK 1 00051 #else 00052 #define USE_TRAP_MASK 0 00053 #endif 00054 00055 #ifndef NSIG 00056 # define NSIG (_SIGMAX + 1) /* For QNX */ 00057 #endif 00058 00059 static const struct signals { 00060 const char *signm; 00061 int signo; 00062 } siglist [] = { 00063 {"EXIT", 0}, 00064 #ifdef SIGHUP 00065 {"HUP", SIGHUP}, 00066 #endif 00067 {"INT", SIGINT}, 00068 #ifdef SIGQUIT 00069 {"QUIT", SIGQUIT}, 00070 #endif 00071 #ifdef SIGILL 00072 {"ILL", SIGILL}, 00073 #endif 00074 #ifdef SIGTRAP 00075 {"TRAP", SIGTRAP}, 00076 #endif 00077 #ifdef SIGIOT 00078 {"IOT", SIGIOT}, 00079 #endif 00080 #ifdef SIGABRT 00081 {"ABRT", SIGABRT}, 00082 #endif 00083 #ifdef SIGEMT 00084 {"EMT", SIGEMT}, 00085 #endif 00086 #ifdef SIGFPE 00087 {"FPE", SIGFPE}, 00088 #endif 00089 #ifdef SIGKILL 00090 {"KILL", SIGKILL}, 00091 #endif 00092 #ifdef SIGBUS 00093 {"BUS", SIGBUS}, 00094 #endif 00095 #ifdef SIGSEGV 00096 {"SEGV", SIGSEGV}, 00097 #endif 00098 #ifdef SIGSYS 00099 {"SYS", SIGSYS}, 00100 #endif 00101 #ifdef SIGPIPE 00102 {"PIPE", SIGPIPE}, 00103 #endif 00104 #ifdef SIGALRM 00105 {"ALRM", SIGALRM}, 00106 #endif 00107 #ifdef SIGTERM 00108 {"TERM", SIGTERM}, 00109 #endif 00110 #ifdef SIGURG 00111 {"URG", SIGURG}, 00112 #endif 00113 #ifdef SIGSTOP 00114 {"STOP", SIGSTOP}, 00115 #endif 00116 #ifdef SIGTSTP 00117 {"TSTP", SIGTSTP}, 00118 #endif 00119 #ifdef SIGCONT 00120 {"CONT", SIGCONT}, 00121 #endif 00122 #ifdef SIGCHLD 00123 {"CHLD", SIGCHLD}, 00124 #endif 00125 #ifdef SIGCLD 00126 {"CLD", SIGCLD}, 00127 #else 00128 # ifdef SIGCHLD 00129 {"CLD", SIGCHLD}, 00130 # endif 00131 #endif 00132 #ifdef SIGTTIN 00133 {"TTIN", SIGTTIN}, 00134 #endif 00135 #ifdef SIGTTOU 00136 {"TTOU", SIGTTOU}, 00137 #endif 00138 #ifdef SIGIO 00139 {"IO", SIGIO}, 00140 #endif 00141 #ifdef SIGXCPU 00142 {"XCPU", SIGXCPU}, 00143 #endif 00144 #ifdef SIGXFSZ 00145 {"XFSZ", SIGXFSZ}, 00146 #endif 00147 #ifdef SIGVTALRM 00148 {"VTALRM", SIGVTALRM}, 00149 #endif 00150 #ifdef SIGPROF 00151 {"PROF", SIGPROF}, 00152 #endif 00153 #ifdef SIGWINCH 00154 {"WINCH", SIGWINCH}, 00155 #endif 00156 #ifdef SIGUSR1 00157 {"USR1", SIGUSR1}, 00158 #endif 00159 #ifdef SIGUSR2 00160 {"USR2", SIGUSR2}, 00161 #endif 00162 #ifdef SIGLOST 00163 {"LOST", SIGLOST}, 00164 #endif 00165 #ifdef SIGMSG 00166 {"MSG", SIGMSG}, 00167 #endif 00168 #ifdef SIGPWR 00169 {"PWR", SIGPWR}, 00170 #endif 00171 #ifdef SIGPOLL 00172 {"POLL", SIGPOLL}, 00173 #endif 00174 #ifdef SIGDANGER 00175 {"DANGER", SIGDANGER}, 00176 #endif 00177 #ifdef SIGMIGRATE 00178 {"MIGRATE", SIGMIGRATE}, 00179 #endif 00180 #ifdef SIGPRE 00181 {"PRE", SIGPRE}, 00182 #endif 00183 #ifdef SIGGRANT 00184 {"GRANT", SIGGRANT}, 00185 #endif 00186 #ifdef SIGRETRACT 00187 {"RETRACT", SIGRETRACT}, 00188 #endif 00189 #ifdef SIGSOUND 00190 {"SOUND", SIGSOUND}, 00191 #endif 00192 #ifdef SIGINFO 00193 {"INFO", SIGINFO}, 00194 #endif 00195 {NULL, 0} 00196 }; 00197 00198 static int 00199 signm2signo(const char *nm) 00200 { 00201 const struct signals *sigs; 00202 00203 for (sigs = siglist; sigs->signm; sigs++) 00204 if (strcmp(sigs->signm, nm) == 0) 00205 return sigs->signo; 00206 return 0; 00207 } 00208 00209 static const char* 00210 signo2signm(int no) 00211 { 00212 const struct signals *sigs; 00213 00214 for (sigs = siglist; sigs->signm; sigs++) 00215 if (sigs->signo == no) 00216 return sigs->signm; 00217 return 0; 00218 } 00219 00220 const char * 00221 ruby_signal_name(int no) 00222 { 00223 return signo2signm(no); 00224 } 00225 00226 /* 00227 * call-seq: 00228 * SignalException.new(sig_name) -> signal_exception 00229 * SignalException.new(sig_number [, name]) -> signal_exception 00230 * 00231 * Construct a new SignalException object. +sig_name+ should be a known 00232 * signal name. 00233 */ 00234 00235 static VALUE 00236 esignal_init(int argc, VALUE *argv, VALUE self) 00237 { 00238 int argnum = 1; 00239 VALUE sig = Qnil; 00240 int signo; 00241 const char *signm; 00242 00243 if (argc > 0) { 00244 sig = rb_check_to_integer(argv[0], "to_int"); 00245 if (!NIL_P(sig)) argnum = 2; 00246 else sig = argv[0]; 00247 } 00248 if (argc < 1 || argnum < argc) { 00249 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", 00250 argc, argnum); 00251 } 00252 if (argnum == 2) { 00253 signo = NUM2INT(sig); 00254 if (signo < 0 || signo > NSIG) { 00255 rb_raise(rb_eArgError, "invalid signal number (%d)", signo); 00256 } 00257 if (argc > 1) { 00258 sig = argv[1]; 00259 } 00260 else { 00261 signm = signo2signm(signo); 00262 if (signm) { 00263 sig = rb_sprintf("SIG%s", signm); 00264 } 00265 else { 00266 sig = rb_sprintf("SIG%u", signo); 00267 } 00268 } 00269 } 00270 else { 00271 signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig); 00272 if (strncmp(signm, "SIG", 3) == 0) signm += 3; 00273 signo = signm2signo(signm); 00274 if (!signo) { 00275 rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm); 00276 } 00277 sig = rb_sprintf("SIG%s", signm); 00278 } 00279 rb_call_super(1, &sig); 00280 rb_iv_set(self, "signo", INT2NUM(signo)); 00281 00282 return self; 00283 } 00284 00285 /* 00286 * call-seq: 00287 * signal_exception.signo -> num 00288 * 00289 * Returns a signal number. 00290 */ 00291 00292 static VALUE 00293 esignal_signo(VALUE self) 00294 { 00295 return rb_iv_get(self, "signo"); 00296 } 00297 00298 /* :nodoc: */ 00299 static VALUE 00300 interrupt_init(int argc, VALUE *argv, VALUE self) 00301 { 00302 VALUE args[2]; 00303 00304 args[0] = INT2FIX(SIGINT); 00305 rb_scan_args(argc, argv, "01", &args[1]); 00306 return rb_call_super(2, args); 00307 } 00308 00309 void 00310 ruby_default_signal(int sig) 00311 { 00312 signal(sig, SIG_DFL); 00313 raise(sig); 00314 } 00315 00316 /* 00317 * call-seq: 00318 * Process.kill(signal, pid, ...) -> fixnum 00319 * 00320 * Sends the given signal to the specified process id(s), or to the 00321 * current process if _pid_ is zero. _signal_ may be an 00322 * integer signal number or a POSIX signal name (either with or without 00323 * a +SIG+ prefix). If _signal_ is negative (or starts 00324 * with a minus sign), kills process groups instead of 00325 * processes. Not all signals are available on all platforms. 00326 * 00327 * pid = fork do 00328 * Signal.trap("HUP") { puts "Ouch!"; exit } 00329 * # ... do some work ... 00330 * end 00331 * # ... 00332 * Process.kill("HUP", pid) 00333 * Process.wait 00334 * 00335 * <em>produces:</em> 00336 * 00337 * Ouch! 00338 * 00339 * If _signal_ is an integer but wrong for signal, 00340 * <code>Errno::EINVAL</code> or +RangeError+ will be raised. 00341 * Otherwise unless _signal_ is a +String+ or a +Symbol+, and a known 00342 * signal name, +ArgumentError+ will be raised. 00343 * 00344 * Also, <code>Errno::ESRCH</code> or +RangeError+ for invalid _pid_, 00345 * <code>Errno::EPERM</code> when failed because of no privilege, 00346 * will be raised. In these cases, signals may have been sent to 00347 * preceding processes. 00348 */ 00349 00350 VALUE 00351 rb_f_kill(int argc, VALUE *argv) 00352 { 00353 #ifndef HAS_KILLPG 00354 #define killpg(pg, sig) kill(-(pg), (sig)) 00355 #endif 00356 int negative = 0; 00357 int sig; 00358 int i; 00359 volatile VALUE str; 00360 const char *s; 00361 00362 rb_secure(2); 00363 if (argc < 2) 00364 rb_raise(rb_eArgError, "wrong number of arguments (%d for at least 2)", argc); 00365 switch (TYPE(argv[0])) { 00366 case T_FIXNUM: 00367 sig = FIX2INT(argv[0]); 00368 break; 00369 00370 case T_SYMBOL: 00371 s = rb_id2name(SYM2ID(argv[0])); 00372 if (!s) rb_raise(rb_eArgError, "bad signal"); 00373 goto str_signal; 00374 00375 case T_STRING: 00376 s = RSTRING_PTR(argv[0]); 00377 str_signal: 00378 if (s[0] == '-') { 00379 negative++; 00380 s++; 00381 } 00382 if (strncmp("SIG", s, 3) == 0) 00383 s += 3; 00384 if((sig = signm2signo(s)) == 0) 00385 rb_raise(rb_eArgError, "unsupported name `SIG%s'", s); 00386 00387 if (negative) 00388 sig = -sig; 00389 break; 00390 00391 default: 00392 str = rb_check_string_type(argv[0]); 00393 if (!NIL_P(str)) { 00394 s = RSTRING_PTR(str); 00395 goto str_signal; 00396 } 00397 rb_raise(rb_eArgError, "bad signal type %s", 00398 rb_obj_classname(argv[0])); 00399 break; 00400 } 00401 00402 if (sig < 0) { 00403 sig = -sig; 00404 for (i=1; i<argc; i++) { 00405 if (killpg(NUM2PIDT(argv[i]), sig) < 0) 00406 rb_sys_fail(0); 00407 } 00408 } 00409 else { 00410 for (i=1; i<argc; i++) { 00411 if (kill(NUM2PIDT(argv[i]), sig) < 0) 00412 rb_sys_fail(0); 00413 } 00414 } 00415 rb_thread_polling(); 00416 return INT2FIX(i-1); 00417 } 00418 00419 static struct { 00420 rb_atomic_t cnt[RUBY_NSIG]; 00421 rb_atomic_t size; 00422 } signal_buff; 00423 00424 #ifdef __dietlibc__ 00425 #define sighandler_t sh_t 00426 #endif 00427 00428 typedef RETSIGTYPE (*sighandler_t)(int); 00429 #ifdef USE_SIGALTSTACK 00430 typedef void ruby_sigaction_t(int, siginfo_t*, void*); 00431 #define SIGINFO_ARG , siginfo_t *info, void *ctx 00432 #else 00433 typedef RETSIGTYPE ruby_sigaction_t(int); 00434 #define SIGINFO_ARG 00435 #endif 00436 00437 #ifdef POSIX_SIGNAL 00438 00439 #ifdef USE_SIGALTSTACK 00440 /* alternate stack for SIGSEGV */ 00441 void 00442 rb_register_sigaltstack(rb_thread_t *th) 00443 { 00444 stack_t newSS, oldSS; 00445 00446 if (!th->altstack) 00447 rb_bug("rb_register_sigaltstack: th->altstack not initialized\n"); 00448 00449 newSS.ss_sp = th->altstack; 00450 newSS.ss_size = ALT_STACK_SIZE; 00451 newSS.ss_flags = 0; 00452 00453 sigaltstack(&newSS, &oldSS); /* ignore error. */ 00454 } 00455 #endif /* USE_SIGALTSTACK */ 00456 00457 static sighandler_t 00458 ruby_signal(int signum, sighandler_t handler) 00459 { 00460 struct sigaction sigact, old; 00461 00462 #if 0 00463 rb_trap_accept_nativethreads[signum] = 0; 00464 #endif 00465 00466 sigemptyset(&sigact.sa_mask); 00467 #ifdef USE_SIGALTSTACK 00468 sigact.sa_sigaction = (ruby_sigaction_t*)handler; 00469 sigact.sa_flags = SA_SIGINFO; 00470 #else 00471 sigact.sa_handler = handler; 00472 sigact.sa_flags = 0; 00473 #endif 00474 00475 #ifdef SA_NOCLDWAIT 00476 if (signum == SIGCHLD && handler == SIG_IGN) 00477 sigact.sa_flags |= SA_NOCLDWAIT; 00478 #endif 00479 #if defined(SA_ONSTACK) && defined(USE_SIGALTSTACK) 00480 if (signum == SIGSEGV || signum == SIGBUS) 00481 sigact.sa_flags |= SA_ONSTACK; 00482 #endif 00483 if (sigaction(signum, &sigact, &old) < 0) { 00484 if (errno != 0 && errno != EINVAL) { 00485 rb_bug_errno("sigaction", errno); 00486 } 00487 } 00488 return old.sa_handler; 00489 } 00490 00491 sighandler_t 00492 posix_signal(int signum, sighandler_t handler) 00493 { 00494 return ruby_signal(signum, handler); 00495 } 00496 00497 #else /* !POSIX_SIGNAL */ 00498 #define ruby_signal(sig,handler) (/* rb_trap_accept_nativethreads[(sig)] = 0,*/ signal((sig),(handler))) 00499 #if 0 /* def HAVE_NATIVETHREAD */ 00500 static sighandler_t 00501 ruby_nativethread_signal(int signum, sighandler_t handler) 00502 { 00503 sighandler_t old; 00504 00505 old = signal(signum, handler); 00506 rb_trap_accept_nativethreads[signum] = 1; 00507 return old; 00508 } 00509 #endif 00510 #endif 00511 00512 static RETSIGTYPE 00513 sighandler(int sig) 00514 { 00515 ATOMIC_INC(signal_buff.cnt[sig]); 00516 ATOMIC_INC(signal_buff.size); 00517 rb_thread_wakeup_timer_thread(); 00518 #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL) 00519 ruby_signal(sig, sighandler); 00520 #endif 00521 } 00522 00523 int 00524 rb_signal_buff_size(void) 00525 { 00526 return signal_buff.size; 00527 } 00528 00529 #if USE_TRAP_MASK 00530 static sigset_t trap_last_mask; 00531 #endif 00532 00533 #if HAVE_PTHREAD_H 00534 #include <pthread.h> 00535 #endif 00536 00537 void 00538 rb_disable_interrupt(void) 00539 { 00540 #if USE_TRAP_MASK 00541 sigset_t mask; 00542 sigfillset(&mask); 00543 sigdelset(&mask, SIGVTALRM); 00544 sigdelset(&mask, SIGSEGV); 00545 pthread_sigmask(SIG_SETMASK, &mask, NULL); 00546 #endif 00547 } 00548 00549 void 00550 rb_enable_interrupt(void) 00551 { 00552 #if USE_TRAP_MASK 00553 sigset_t mask; 00554 sigemptyset(&mask); 00555 pthread_sigmask(SIG_SETMASK, &mask, NULL); 00556 #endif 00557 } 00558 00559 int 00560 rb_get_next_signal(void) 00561 { 00562 int i, sig = 0; 00563 00564 if (signal_buff.size != 0) { 00565 for (i=1; i<RUBY_NSIG; i++) { 00566 if (signal_buff.cnt[i] > 0) { 00567 rb_disable_interrupt(); 00568 { 00569 ATOMIC_DEC(signal_buff.cnt[i]); 00570 ATOMIC_DEC(signal_buff.size); 00571 } 00572 rb_enable_interrupt(); 00573 sig = i; 00574 break; 00575 } 00576 } 00577 } 00578 return sig; 00579 } 00580 00581 00582 #ifdef USE_SIGALTSTACK 00583 static void 00584 check_stack_overflow(const void *addr) 00585 { 00586 int ruby_stack_overflowed_p(const rb_thread_t *, const void *); 00587 NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th)); 00588 rb_thread_t *th = GET_THREAD(); 00589 if (ruby_stack_overflowed_p(th, addr)) { 00590 ruby_thread_stack_overflow(th); 00591 } 00592 } 00593 #define CHECK_STACK_OVERFLOW() check_stack_overflow(info->si_addr) 00594 #else 00595 #define CHECK_STACK_OVERFLOW() (void)0 00596 #endif 00597 00598 #ifdef SIGBUS 00599 static RETSIGTYPE 00600 sigbus(int sig SIGINFO_ARG) 00601 { 00602 /* 00603 * Mac OS X makes KERN_PROTECTION_FAILURE when thread touch guard page. 00604 * and it's delivered as SIGBUS instaed of SIGSEGV to userland. It's crazy 00605 * wrong IMHO. but anyway we have to care it. Sigh. 00606 */ 00607 #if defined __APPLE__ 00608 CHECK_STACK_OVERFLOW(); 00609 #endif 00610 rb_bug("Bus Error"); 00611 } 00612 #endif 00613 00614 #ifdef SIGSEGV 00615 static void ruby_abort(void) 00616 { 00617 #ifdef __sun 00618 /* Solaris's abort() is async signal unsafe. Of course, it is not 00619 * POSIX compliant. 00620 */ 00621 raise(SIGABRT); 00622 #else 00623 abort(); 00624 #endif 00625 00626 } 00627 00628 static int segv_received = 0; 00629 extern int ruby_disable_gc_stress; 00630 00631 static RETSIGTYPE 00632 sigsegv(int sig SIGINFO_ARG) 00633 { 00634 if (segv_received) { 00635 char msg[] = "SEGV received in SEGV handler\n"; 00636 write(2, msg, sizeof(msg)); 00637 ruby_abort(); 00638 } 00639 00640 CHECK_STACK_OVERFLOW(); 00641 00642 segv_received = 1; 00643 ruby_disable_gc_stress = 1; 00644 rb_bug("Segmentation fault"); 00645 } 00646 #endif 00647 00648 static void 00649 signal_exec(VALUE cmd, int safe, int sig) 00650 { 00651 VALUE signum = INT2NUM(sig); 00652 rb_eval_cmd(cmd, rb_ary_new3(1, signum), safe); 00653 } 00654 00655 void 00656 rb_trap_exit(void) 00657 { 00658 rb_vm_t *vm = GET_VM(); 00659 VALUE trap_exit = vm->trap_list[0].cmd; 00660 00661 if (trap_exit) { 00662 vm->trap_list[0].cmd = 0; 00663 signal_exec(trap_exit, vm->trap_list[0].safe, 0); 00664 } 00665 } 00666 00667 void 00668 rb_signal_exec(rb_thread_t *th, int sig) 00669 { 00670 rb_vm_t *vm = GET_VM(); 00671 VALUE cmd = vm->trap_list[sig].cmd; 00672 int safe = vm->trap_list[sig].safe; 00673 00674 if (cmd == 0) { 00675 switch (sig) { 00676 case SIGINT: 00677 rb_interrupt(); 00678 break; 00679 #ifdef SIGHUP 00680 case SIGHUP: 00681 #endif 00682 #ifdef SIGQUIT 00683 case SIGQUIT: 00684 #endif 00685 #ifdef SIGTERM 00686 case SIGTERM: 00687 #endif 00688 #ifdef SIGALRM 00689 case SIGALRM: 00690 #endif 00691 #ifdef SIGUSR1 00692 case SIGUSR1: 00693 #endif 00694 #ifdef SIGUSR2 00695 case SIGUSR2: 00696 #endif 00697 rb_threadptr_signal_raise(th, sig); 00698 break; 00699 } 00700 } 00701 else if (cmd == Qundef) { 00702 rb_threadptr_signal_exit(th); 00703 } 00704 else { 00705 signal_exec(cmd, safe, sig); 00706 } 00707 } 00708 00709 struct trap_arg { 00710 #if USE_TRAP_MASK 00711 sigset_t mask; 00712 #endif 00713 int sig; 00714 sighandler_t func; 00715 VALUE cmd; 00716 }; 00717 00718 static sighandler_t 00719 default_handler(int sig) 00720 { 00721 sighandler_t func; 00722 switch (sig) { 00723 case SIGINT: 00724 #ifdef SIGHUP 00725 case SIGHUP: 00726 #endif 00727 #ifdef SIGQUIT 00728 case SIGQUIT: 00729 #endif 00730 #ifdef SIGTERM 00731 case SIGTERM: 00732 #endif 00733 #ifdef SIGALRM 00734 case SIGALRM: 00735 #endif 00736 #ifdef SIGUSR1 00737 case SIGUSR1: 00738 #endif 00739 #ifdef SIGUSR2 00740 case SIGUSR2: 00741 #endif 00742 func = sighandler; 00743 break; 00744 #ifdef SIGBUS 00745 case SIGBUS: 00746 func = (sighandler_t)sigbus; 00747 break; 00748 #endif 00749 #ifdef SIGSEGV 00750 case SIGSEGV: 00751 func = (sighandler_t)sigsegv; 00752 # ifdef USE_SIGALTSTACK 00753 rb_register_sigaltstack(GET_THREAD()); 00754 # endif 00755 break; 00756 #endif 00757 #ifdef SIGPIPE 00758 case SIGPIPE: 00759 func = SIG_IGN; 00760 break; 00761 #endif 00762 default: 00763 func = SIG_DFL; 00764 break; 00765 } 00766 00767 return func; 00768 } 00769 00770 static sighandler_t 00771 trap_handler(VALUE *cmd, int sig) 00772 { 00773 sighandler_t func = sighandler; 00774 VALUE command; 00775 00776 if (NIL_P(*cmd)) { 00777 func = SIG_IGN; 00778 } 00779 else { 00780 command = rb_check_string_type(*cmd); 00781 if (NIL_P(command) && SYMBOL_P(*cmd)) { 00782 command = rb_id2str(SYM2ID(*cmd)); 00783 if (!command) rb_raise(rb_eArgError, "bad handler"); 00784 } 00785 if (!NIL_P(command)) { 00786 SafeStringValue(command); /* taint check */ 00787 *cmd = command; 00788 switch (RSTRING_LEN(command)) { 00789 case 0: 00790 goto sig_ign; 00791 break; 00792 case 14: 00793 if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) { 00794 func = SIG_DFL; 00795 *cmd = 0; 00796 } 00797 break; 00798 case 7: 00799 if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) { 00800 sig_ign: 00801 func = SIG_IGN; 00802 *cmd = 0; 00803 } 00804 else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) { 00805 sig_dfl: 00806 func = default_handler(sig); 00807 *cmd = 0; 00808 } 00809 else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) { 00810 goto sig_dfl; 00811 } 00812 break; 00813 case 6: 00814 if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) { 00815 goto sig_ign; 00816 } 00817 break; 00818 case 4: 00819 if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) { 00820 *cmd = Qundef; 00821 } 00822 break; 00823 } 00824 } 00825 else { 00826 rb_proc_t *proc; 00827 GetProcPtr(*cmd, proc); 00828 } 00829 } 00830 00831 return func; 00832 } 00833 00834 static int 00835 trap_signm(VALUE vsig) 00836 { 00837 int sig = -1; 00838 const char *s; 00839 00840 switch (TYPE(vsig)) { 00841 case T_FIXNUM: 00842 sig = FIX2INT(vsig); 00843 if (sig < 0 || sig >= NSIG) { 00844 rb_raise(rb_eArgError, "invalid signal number (%d)", sig); 00845 } 00846 break; 00847 00848 case T_SYMBOL: 00849 s = rb_id2name(SYM2ID(vsig)); 00850 if (!s) rb_raise(rb_eArgError, "bad signal"); 00851 goto str_signal; 00852 00853 default: 00854 s = StringValuePtr(vsig); 00855 00856 str_signal: 00857 if (strncmp("SIG", s, 3) == 0) 00858 s += 3; 00859 sig = signm2signo(s); 00860 if (sig == 0 && strcmp(s, "EXIT") != 0) 00861 rb_raise(rb_eArgError, "unsupported signal SIG%s", s); 00862 } 00863 return sig; 00864 } 00865 00866 static VALUE 00867 trap(struct trap_arg *arg) 00868 { 00869 sighandler_t oldfunc, func = arg->func; 00870 VALUE oldcmd, command = arg->cmd; 00871 int sig = arg->sig; 00872 rb_vm_t *vm = GET_VM(); 00873 00874 oldfunc = ruby_signal(sig, func); 00875 oldcmd = vm->trap_list[sig].cmd; 00876 switch (oldcmd) { 00877 case 0: 00878 if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE"); 00879 else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT"); 00880 else oldcmd = Qnil; 00881 break; 00882 case Qundef: 00883 oldcmd = rb_str_new2("EXIT"); 00884 break; 00885 } 00886 00887 vm->trap_list[sig].cmd = command; 00888 vm->trap_list[sig].safe = rb_safe_level(); 00889 /* enable at least specified signal. */ 00890 #if USE_TRAP_MASK 00891 sigdelset(&arg->mask, sig); 00892 #endif 00893 return oldcmd; 00894 } 00895 00896 #if USE_TRAP_MASK 00897 static VALUE 00898 trap_ensure(struct trap_arg *arg) 00899 { 00900 /* enable interrupt */ 00901 pthread_sigmask(SIG_SETMASK, &arg->mask, NULL); 00902 trap_last_mask = arg->mask; 00903 return 0; 00904 } 00905 #endif 00906 00907 void 00908 rb_trap_restore_mask(void) 00909 { 00910 #if USE_TRAP_MASK 00911 pthread_sigmask(SIG_SETMASK, &trap_last_mask, NULL); 00912 #endif 00913 } 00914 00915 /* 00916 * call-seq: 00917 * Signal.trap( signal, command ) -> obj 00918 * Signal.trap( signal ) {| | block } -> obj 00919 * 00920 * Specifies the handling of signals. The first parameter is a signal 00921 * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a 00922 * signal number. The characters ``SIG'' may be omitted from the 00923 * signal name. The command or block specifies code to be run when the 00924 * signal is raised. 00925 * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal 00926 * will be ignored. 00927 * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler 00928 * will be invoked. 00929 * If the command is ``EXIT'', the script will be terminated by the signal. 00930 * If the command is ``SYSTEM_DEFAULT'', the operating system's default 00931 * handler will be invoked. 00932 * Otherwise, the given command or block will be run. 00933 * The special signal name ``EXIT'' or signal number zero will be 00934 * invoked just prior to program termination. 00935 * trap returns the previous handler for the given signal. 00936 * 00937 * Signal.trap(0, proc { puts "Terminating: #{$$}" }) 00938 * Signal.trap("CLD") { puts "Child died" } 00939 * fork && Process.wait 00940 * 00941 * produces: 00942 * Terminating: 27461 00943 * Child died 00944 * Terminating: 27460 00945 */ 00946 static VALUE 00947 sig_trap(int argc, VALUE *argv) 00948 { 00949 struct trap_arg arg; 00950 00951 rb_secure(2); 00952 if (argc < 1 || argc > 2) { 00953 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc); 00954 } 00955 00956 arg.sig = trap_signm(argv[0]); 00957 if (argc == 1) { 00958 arg.cmd = rb_block_proc(); 00959 arg.func = sighandler; 00960 } 00961 else { 00962 arg.cmd = argv[1]; 00963 arg.func = trap_handler(&arg.cmd, arg.sig); 00964 } 00965 00966 if (OBJ_TAINTED(arg.cmd)) { 00967 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap"); 00968 } 00969 #if USE_TRAP_MASK 00970 { 00971 sigset_t fullmask; 00972 00973 /* disable interrupt */ 00974 sigfillset(&fullmask); 00975 pthread_sigmask(SIG_BLOCK, &fullmask, &arg.mask); 00976 00977 return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg); 00978 } 00979 #else 00980 return trap(&arg); 00981 #endif 00982 } 00983 00984 /* 00985 * call-seq: 00986 * Signal.list -> a_hash 00987 * 00988 * Returns a list of signal names mapped to the corresponding 00989 * underlying signal numbers. 00990 * 00991 * Signal.list #=> {"EXIT"=>0, "HUP"=>1, "INT"=>2, "QUIT"=>3, "ILL"=>4, "TRAP"=>5, "IOT"=>6, "ABRT"=>6, "FPE"=>8, "KILL"=>9, "BUS"=>7, "SEGV"=>11, "SYS"=>31, "PIPE"=>13, "ALRM"=>14, "TERM"=>15, "URG"=>23, "STOP"=>19, "TSTP"=>20, "CONT"=>18, "CHLD"=>17, "CLD"=>17, "TTIN"=>21, "TTOU"=>22, "IO"=>29, "XCPU"=>24, "XFSZ"=>25, "VTALRM"=>26, "PROF"=>27, "WINCH"=>28, "USR1"=>10, "USR2"=>12, "PWR"=>30, "POLL"=>29} 00992 */ 00993 static VALUE 00994 sig_list(void) 00995 { 00996 VALUE h = rb_hash_new(); 00997 const struct signals *sigs; 00998 00999 for (sigs = siglist; sigs->signm; sigs++) { 01000 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo)); 01001 } 01002 return h; 01003 } 01004 01005 static void 01006 install_sighandler(int signum, sighandler_t handler) 01007 { 01008 sighandler_t old; 01009 01010 old = ruby_signal(signum, handler); 01011 if (old != SIG_DFL) { 01012 ruby_signal(signum, old); 01013 } 01014 } 01015 01016 #if defined(SIGCLD) || defined(SIGCHLD) 01017 static void 01018 init_sigchld(int sig) 01019 { 01020 sighandler_t oldfunc; 01021 #if USE_TRAP_MASK 01022 sigset_t mask; 01023 sigset_t fullmask; 01024 01025 /* disable interrupt */ 01026 sigfillset(&fullmask); 01027 pthread_sigmask(SIG_BLOCK, &fullmask, &mask); 01028 #endif 01029 01030 oldfunc = ruby_signal(sig, SIG_DFL); 01031 if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) { 01032 ruby_signal(sig, oldfunc); 01033 } else { 01034 GET_VM()->trap_list[sig].cmd = 0; 01035 } 01036 01037 #if USE_TRAP_MASK 01038 sigdelset(&mask, sig); 01039 pthread_sigmask(SIG_SETMASK, &mask, NULL); 01040 trap_last_mask = mask; 01041 #endif 01042 } 01043 #endif 01044 01045 void 01046 ruby_sig_finalize(void) 01047 { 01048 sighandler_t oldfunc; 01049 01050 oldfunc = ruby_signal(SIGINT, SIG_IGN); 01051 if (oldfunc == sighandler) { 01052 ruby_signal(SIGINT, SIG_DFL); 01053 } 01054 } 01055 01056 01057 int ruby_enable_coredump = 0; 01058 #ifndef RUBY_DEBUG_ENV 01059 #define ruby_enable_coredump 0 01060 #endif 01061 01062 /* 01063 * Many operating systems allow signals to be sent to running 01064 * processes. Some signals have a defined effect on the process, while 01065 * others may be trapped at the code level and acted upon. For 01066 * example, your process may trap the USR1 signal and use it to toggle 01067 * debugging, and may use TERM to initiate a controlled shutdown. 01068 * 01069 * pid = fork do 01070 * Signal.trap("USR1") do 01071 * $debug = !$debug 01072 * puts "Debug now: #$debug" 01073 * end 01074 * Signal.trap("TERM") do 01075 * puts "Terminating..." 01076 * shutdown() 01077 * end 01078 * # . . . do some work . . . 01079 * end 01080 * 01081 * Process.detach(pid) 01082 * 01083 * # Controlling program: 01084 * Process.kill("USR1", pid) 01085 * # ... 01086 * Process.kill("USR1", pid) 01087 * # ... 01088 * Process.kill("TERM", pid) 01089 * 01090 * produces: 01091 * Debug now: true 01092 * Debug now: false 01093 * Terminating... 01094 * 01095 * The list of available signal names and their interpretation is 01096 * system dependent. Signal delivery semantics may also vary between 01097 * systems; in particular signal delivery may not always be reliable. 01098 */ 01099 void 01100 Init_signal(void) 01101 { 01102 VALUE mSignal = rb_define_module("Signal"); 01103 01104 rb_define_global_function("trap", sig_trap, -1); 01105 rb_define_module_function(mSignal, "trap", sig_trap, -1); 01106 rb_define_module_function(mSignal, "list", sig_list, 0); 01107 01108 rb_define_method(rb_eSignal, "initialize", esignal_init, -1); 01109 rb_define_method(rb_eSignal, "signo", esignal_signo, 0); 01110 rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message")); 01111 rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1); 01112 01113 install_sighandler(SIGINT, sighandler); 01114 #ifdef SIGHUP 01115 install_sighandler(SIGHUP, sighandler); 01116 #endif 01117 #ifdef SIGQUIT 01118 install_sighandler(SIGQUIT, sighandler); 01119 #endif 01120 #ifdef SIGTERM 01121 install_sighandler(SIGTERM, sighandler); 01122 #endif 01123 #ifdef SIGALRM 01124 install_sighandler(SIGALRM, sighandler); 01125 #endif 01126 #ifdef SIGUSR1 01127 install_sighandler(SIGUSR1, sighandler); 01128 #endif 01129 #ifdef SIGUSR2 01130 install_sighandler(SIGUSR2, sighandler); 01131 #endif 01132 01133 if (!ruby_enable_coredump) { 01134 #ifdef SIGBUS 01135 install_sighandler(SIGBUS, (sighandler_t)sigbus); 01136 #endif 01137 #ifdef SIGSEGV 01138 # ifdef USE_SIGALTSTACK 01139 rb_register_sigaltstack(GET_THREAD()); 01140 # endif 01141 install_sighandler(SIGSEGV, (sighandler_t)sigsegv); 01142 #endif 01143 } 01144 #ifdef SIGPIPE 01145 install_sighandler(SIGPIPE, SIG_IGN); 01146 #endif 01147 01148 #if defined(SIGCLD) 01149 init_sigchld(SIGCLD); 01150 #elif defined(SIGCHLD) 01151 init_sigchld(SIGCHLD); 01152 #endif 01153 } 01154
1.7.6.1