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