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