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