diff options
author | yugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-08-25 15:13:14 +0000 |
---|---|---|
committer | yugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-08-25 15:13:14 +0000 |
commit | d0233291bc8a5068e52c69c210e5979e5324b5bc (patch) | |
tree | 7d9459449c33792c63eeb7baa071e76352e0baab /trunk/signal.c | |
parent | 0dc342de848a642ecce8db697b8fecd83a63e117 (diff) | |
parent | 72eaacaa15256ab95c3b52ea386f88586fb9da40 (diff) |
re-adding tag v1_9_0_4 as an alias of trunk@18848v1_9_0_4
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_9_0_4@18849 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'trunk/signal.c')
-rw-r--r-- | trunk/signal.c | 1128 |
1 files changed, 0 insertions, 1128 deletions
diff --git a/trunk/signal.c b/trunk/signal.c deleted file mode 100644 index b110e16cb7..0000000000 --- a/trunk/signal.c +++ /dev/null @@ -1,1128 +0,0 @@ -/********************************************************************** - - signal.c - - - $Author$ - created at: Tue Dec 20 10:13:44 JST 1994 - - Copyright (C) 1993-2007 Yukihiro Matsumoto - Copyright (C) 2000 Network Applied Communication Laboratory, Inc. - Copyright (C) 2000 Information-technology Promotion Agency, Japan - -**********************************************************************/ - -#include "ruby/ruby.h" -#include "ruby/signal.h" -#include "ruby/node.h" -#include "vm_core.h" -#include <signal.h> -#include <stdio.h> - -#ifdef __BEOS__ -#undef SIGBUS -#endif - -#if defined HAVE_SIGPROCMASK || defined HAVE_SIGSETMASK -#define USE_TRAP_MASK 1 -#else -#define USE_TRAP_MASK 0 -#endif - -#ifndef NSIG -# ifdef DJGPP -# define NSIG SIGMAX -# else -# define NSIG (_SIGMAX + 1) /* For QNX */ -# endif -#endif - -static const struct signals { - const char *signm; - int signo; -} siglist [] = { - {"EXIT", 0}, -#ifdef SIGHUP - {"HUP", SIGHUP}, -#endif - {"INT", SIGINT}, -#ifdef SIGQUIT - {"QUIT", SIGQUIT}, -#endif -#ifdef SIGILL - {"ILL", SIGILL}, -#endif -#ifdef SIGTRAP - {"TRAP", SIGTRAP}, -#endif -#ifdef SIGIOT - {"IOT", SIGIOT}, -#endif -#ifdef SIGABRT - {"ABRT", SIGABRT}, -#endif -#ifdef SIGEMT - {"EMT", SIGEMT}, -#endif -#ifdef SIGFPE - {"FPE", SIGFPE}, -#endif -#ifdef SIGKILL - {"KILL", SIGKILL}, -#endif -#ifdef SIGBUS - {"BUS", SIGBUS}, -#endif -#ifdef SIGSEGV - {"SEGV", SIGSEGV}, -#endif -#ifdef SIGSYS - {"SYS", SIGSYS}, -#endif -#ifdef SIGPIPE - {"PIPE", SIGPIPE}, -#endif -#ifdef SIGALRM - {"ALRM", SIGALRM}, -#endif -#ifdef SIGTERM - {"TERM", SIGTERM}, -#endif -#ifdef SIGURG - {"URG", SIGURG}, -#endif -#ifdef SIGSTOP - {"STOP", SIGSTOP}, -#endif -#ifdef SIGTSTP - {"TSTP", SIGTSTP}, -#endif -#ifdef SIGCONT - {"CONT", SIGCONT}, -#endif -#ifdef SIGCHLD - {"CHLD", SIGCHLD}, -#endif -#ifdef SIGCLD - {"CLD", SIGCLD}, -#else -# ifdef SIGCHLD - {"CLD", SIGCHLD}, -# endif -#endif -#ifdef SIGTTIN - {"TTIN", SIGTTIN}, -#endif -#ifdef SIGTTOU - {"TTOU", SIGTTOU}, -#endif -#ifdef SIGIO - {"IO", SIGIO}, -#endif -#ifdef SIGXCPU - {"XCPU", SIGXCPU}, -#endif -#ifdef SIGXFSZ - {"XFSZ", SIGXFSZ}, -#endif -#ifdef SIGVTALRM - {"VTALRM", SIGVTALRM}, -#endif -#ifdef SIGPROF - {"PROF", SIGPROF}, -#endif -#ifdef SIGWINCH - {"WINCH", SIGWINCH}, -#endif -#ifdef SIGUSR1 - {"USR1", SIGUSR1}, -#endif -#ifdef SIGUSR2 - {"USR2", SIGUSR2}, -#endif -#ifdef SIGLOST - {"LOST", SIGLOST}, -#endif -#ifdef SIGMSG - {"MSG", SIGMSG}, -#endif -#ifdef SIGPWR - {"PWR", SIGPWR}, -#endif -#ifdef SIGPOLL - {"POLL", SIGPOLL}, -#endif -#ifdef SIGDANGER - {"DANGER", SIGDANGER}, -#endif -#ifdef SIGMIGRATE - {"MIGRATE", SIGMIGRATE}, -#endif -#ifdef SIGPRE - {"PRE", SIGPRE}, -#endif -#ifdef SIGGRANT - {"GRANT", SIGGRANT}, -#endif -#ifdef SIGRETRACT - {"RETRACT", SIGRETRACT}, -#endif -#ifdef SIGSOUND - {"SOUND", SIGSOUND}, -#endif -#ifdef SIGINFO - {"INFO", SIGINFO}, -#endif - {NULL, 0} -}; - -static int -signm2signo(const char *nm) -{ - const struct signals *sigs; - - for (sigs = siglist; sigs->signm; sigs++) - if (strcmp(sigs->signm, nm) == 0) - return sigs->signo; - return 0; -} - -static const char* -signo2signm(int no) -{ - const struct signals *sigs; - - for (sigs = siglist; sigs->signm; sigs++) - if (sigs->signo == no) - return sigs->signm; - return 0; -} - -const char * -ruby_signal_name(int no) -{ - return signo2signm(no); -} - -/* - * call-seq: - * SignalException.new(sig) => signal_exception - * - * Construct a new SignalException object. +sig+ should be a known - * signal name, or a signal number. - */ - -static VALUE -esignal_init(int argc, VALUE *argv, VALUE self) -{ - int argnum = 1; - VALUE sig = Qnil; - int signo; - const char *signm; - - if (argc > 0) { - sig = rb_check_to_integer(argv[0], "to_int"); - if (!NIL_P(sig)) argnum = 2; - else sig = argv[0]; - } - if (argc < 1 || argnum < argc) { - rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", - argc, argnum); - } - if (argnum == 2) { - signo = NUM2INT(sig); - if (signo < 0 || signo > NSIG) { - rb_raise(rb_eArgError, "invalid signal number (%d)", signo); - } - if (argc > 1) { - sig = argv[1]; - } - else { - signm = signo2signm(signo); - if (signm) { - sig = rb_sprintf("SIG%s", signm); - } - else { - sig = rb_sprintf("SIG%u", signo); - } - } - } - else { - signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig); - if (strncmp(signm, "SIG", 3) == 0) signm += 3; - signo = signm2signo(signm); - if (!signo) { - rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm); - } - sig = rb_sprintf("SIG%s", signm); - } - rb_call_super(1, &sig); - rb_iv_set(self, "signo", INT2NUM(signo)); - - return self; -} - -/* - * call-seq: - * signal_exception.signo => num - * - * Returns a signal number. - */ - -static VALUE -esignal_signo(VALUE self) -{ - return rb_iv_get(self, "signo"); -} - -static VALUE -interrupt_init(int argc, VALUE *argv, VALUE self) -{ - VALUE args[2]; - - args[0] = INT2FIX(SIGINT); - rb_scan_args(argc, argv, "01", &args[1]); - return rb_call_super(2, args); -} - -void -ruby_default_signal(int sig) -{ -#ifndef MACOS_UNUSE_SIGNAL - signal(sig, SIG_DFL); - raise(sig); -#endif -} - -/* - * call-seq: - * Process.kill(signal, pid, ...) => fixnum - * - * Sends the given signal to the specified process id(s), or to the - * current process if _pid_ is zero. _signal_ may be an - * integer signal number or a POSIX signal name (either with or without - * a +SIG+ prefix). If _signal_ is negative (or starts - * with a minus sign), kills process groups instead of - * processes. Not all signals are available on all platforms. - * - * pid = fork do - * Signal.trap("HUP") { puts "Ouch!"; exit } - * # ... do some work ... - * end - * # ... - * Process.kill("HUP", pid) - * Process.wait - * - * <em>produces:</em> - * - * Ouch! - */ - -VALUE -rb_f_kill(int argc, VALUE *argv) -{ -#ifndef HAS_KILLPG -#define killpg(pg, sig) kill(-(pg), sig) -#endif - int negative = 0; - int sig; - int i; - const char *s; - - rb_secure(2); - if (argc < 2) - rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)"); - switch (TYPE(argv[0])) { - case T_FIXNUM: - sig = FIX2INT(argv[0]); - break; - - case T_SYMBOL: - s = rb_id2name(SYM2ID(argv[0])); - if (!s) rb_raise(rb_eArgError, "bad signal"); - goto str_signal; - - case T_STRING: - s = RSTRING_PTR(argv[0]); - if (s[0] == '-') { - negative++; - s++; - } - str_signal: - if (strncmp("SIG", s, 3) == 0) - s += 3; - if((sig = signm2signo(s)) == 0) - rb_raise(rb_eArgError, "unsupported name `SIG%s'", s); - - if (negative) - sig = -sig; - break; - - default: - { - VALUE str; - - str = rb_check_string_type(argv[0]); - if (!NIL_P(str)) { - s = RSTRING_PTR(str); - goto str_signal; - } - rb_raise(rb_eArgError, "bad signal type %s", - rb_obj_classname(argv[0])); - } - break; - } - - if (sig < 0) { - sig = -sig; - for (i=1; i<argc; i++) { - if (killpg(NUM2PIDT(argv[i]), sig) < 0) - rb_sys_fail(0); - } - } - else { - for (i=1; i<argc; i++) { - if (kill(NUM2PIDT(argv[i]), sig) < 0) - rb_sys_fail(0); - } - } - rb_thread_polling(); - return INT2FIX(i-1); -} - -static struct { - VALUE cmd; - int safe; -} trap_list[NSIG]; -static rb_atomic_t trap_pending_list[NSIG]; -#if 0 -static char rb_trap_accept_nativethreads[NSIG]; -#endif -rb_atomic_t rb_trap_pending; -rb_atomic_t rb_trap_immediate; -int rb_prohibit_interrupt = 1; - -VALUE -rb_get_trap_cmd(int sig) -{ - return trap_list[sig].cmd; -} - -void -rb_gc_mark_trap_list(void) -{ -#ifndef MACOS_UNUSE_SIGNAL - int i; - - for (i=0; i<NSIG; i++) { - if (trap_list[i].cmd) - rb_gc_mark(trap_list[i].cmd); - } -#endif /* MACOS_UNUSE_SIGNAL */ -} - -#ifdef __dietlibc__ -#define sighandler_t sh_t -#endif - -typedef RETSIGTYPE (*sighandler_t)(int); - -#ifdef POSIX_SIGNAL -static sighandler_t -ruby_signal(int signum, sighandler_t handler) -{ - struct sigaction sigact, old; - -#if 0 - rb_trap_accept_nativethreads[signum] = 0; -#endif - - sigemptyset(&sigact.sa_mask); -#ifdef SA_SIGINFO - sigact.sa_sigaction = (void (*)(int, siginfo_t*, void*))handler; - sigact.sa_flags = SA_SIGINFO; -#else - sigact.sa_handler = handler; - sigact.sa_flags = 0; -#endif - -#ifdef SA_NOCLDWAIT - if (signum == SIGCHLD && handler == SIG_IGN) - sigact.sa_flags |= SA_NOCLDWAIT; -#endif - sigaction(signum, &sigact, &old); - return old.sa_handler; -} - -sighandler_t -posix_signal(int signum, sighandler_t handler) -{ - return ruby_signal(signum, handler); -} - -#else /* !POSIX_SIGNAL */ -#define ruby_signal(sig,handler) (/* rb_trap_accept_nativethreads[sig] = 0,*/ signal((sig),(handler))) -#if 0 /* def HAVE_NATIVETHREAD */ -static sighandler_t -ruby_nativethread_signal(int signum, sighandler_t handler) -{ - sighandler_t old; - - old = signal(signum, handler); - rb_trap_accept_nativethreads[signum] = 1; - return old; -} -#endif -#endif - -static RETSIGTYPE -sighandler(int sig) -{ - rb_vm_t *vm = GET_VM(); /* fix me for Multi-VM */ - ATOMIC_INC(vm->signal_buff[sig]); - ATOMIC_INC(vm->buffered_signal_size); - -#if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL) - ruby_signal(sig, sighandler); -#endif -} - -#if USE_TRAP_MASK -# ifdef HAVE_SIGPROCMASK -static sigset_t trap_last_mask; -# else -static int trap_last_mask; -# endif -#endif - -#if HAVE_PTHREAD_H -#include <pthread.h> -#endif - -void -rb_disable_interrupt(void) -{ -#ifndef _WIN32 - sigset_t mask; - sigfillset(&mask); - sigdelset(&mask, SIGVTALRM); - sigdelset(&mask, SIGSEGV); - pthread_sigmask(SIG_SETMASK, &mask, NULL); -#endif -} - -void -rb_enable_interrupt(void) -{ -#ifndef _WIN32 - sigset_t mask; - sigemptyset(&mask); - pthread_sigmask(SIG_SETMASK, &mask, NULL); -#endif -} - -int -rb_get_next_signal(rb_vm_t *vm) -{ - int i, sig = 0; - - for (i=1; i<RUBY_NSIG; i++) { - if (vm->signal_buff[i] > 0) { - rb_disable_interrupt(); - { - ATOMIC_DEC(vm->signal_buff[i]); - ATOMIC_DEC(vm->buffered_signal_size); - } - rb_enable_interrupt(); - sig = i; - break; - } - } - return sig; -} - -#ifdef SIGBUS -static RETSIGTYPE -sigbus(int sig) -{ - rb_bug("Bus Error"); -} -#endif - -#ifdef SIGSEGV -static int segv_received = 0; -static RETSIGTYPE -sigsegv(int sig) -{ - if (segv_received) { - fprintf(stderr, "SEGV recieved in SEGV handler\n"); - exit(EXIT_FAILURE); - } - else { - extern int ruby_disable_gc_stress; - segv_received = 1; - ruby_disable_gc_stress = 1; - rb_bug("Segmentation fault"); - } -} -#endif - -#ifdef SIGPIPE -static RETSIGTYPE -sigpipe(int sig) -{ - /* do nothing */ -} -#endif - -static void -signal_exec(VALUE cmd, int sig) -{ - rb_proc_t *proc; - VALUE signum = INT2FIX(sig); - - if (TYPE(cmd) == T_STRING) { - rb_eval_cmd(cmd, rb_ary_new3(1, signum), trap_list[sig].safe); - return; - } - GetProcPtr(cmd, proc); - vm_invoke_proc(GET_THREAD(), proc, proc->block.self, 1, &signum, 0); -} - -void -rb_trap_exit(void) -{ -#ifndef MACOS_UNUSE_SIGNAL - if (trap_list[0].cmd) { - VALUE trap_exit = trap_list[0].cmd; - - trap_list[0].cmd = 0; - signal_exec(trap_exit, 0); - } -#endif -} - -void -rb_signal_exec(rb_thread_t *th, int sig) -{ - VALUE cmd = rb_get_trap_cmd(sig); - - if (cmd == 0) { - switch (sig) { - case SIGINT: - rb_interrupt(); - break; -#ifdef SIGHUP - case SIGHUP: -#endif -#ifdef SIGQUIT - case SIGQUIT: -#endif -#ifdef SIGTERM - case SIGTERM: -#endif -#ifdef SIGALRM - case SIGALRM: -#endif -#ifdef SIGUSR1 - case SIGUSR1: -#endif -#ifdef SIGUSR2 - case SIGUSR2: -#endif - rb_thread_signal_raise(th, sig); - break; - } - } - else if (cmd == Qundef) { - rb_thread_signal_exit(th); - } - else { - signal_exec(cmd, sig); - } -} - -void -rb_trap_exec(void) -{ -#ifndef MACOS_UNUSE_SIGNAL - int i; - - for (i=0; i<NSIG; i++) { - if (trap_pending_list[i]) { - trap_pending_list[i] = 0; - rb_signal_exec(GET_THREAD(), i); - } - } -#endif /* MACOS_UNUSE_SIGNAL */ - rb_trap_pending = 0; -} - -struct trap_arg { -#if USE_TRAP_MASK -# ifdef HAVE_SIGPROCMASK - sigset_t mask; -# else - int mask; -# endif -#endif - int sig; - sighandler_t func; - VALUE cmd; -}; - -static sighandler_t -default_handler(int sig) -{ - sighandler_t func; - switch (sig) { - case SIGINT: -#ifdef SIGHUP - case SIGHUP: -#endif -#ifdef SIGQUIT - case SIGQUIT: -#endif -#ifdef SIGTERM - case SIGTERM: -#endif -#ifdef SIGALRM - case SIGALRM: -#endif -#ifdef SIGUSR1 - case SIGUSR1: -#endif -#ifdef SIGUSR2 - case SIGUSR2: -#endif - func = sighandler; - break; -#ifdef SIGBUS - case SIGBUS: - func = sigbus; - break; -#endif -#ifdef SIGSEGV - case SIGSEGV: - func = sigsegv; - break; -#endif -#ifdef SIGPIPE - case SIGPIPE: - func = sigpipe; - break; -#endif - default: - func = SIG_DFL; - break; - } - - return func; -} - -static sighandler_t -trap_handler(VALUE *cmd, int sig) -{ - sighandler_t func = sighandler; - VALUE command; - - if (NIL_P(*cmd)) { - func = SIG_IGN; - } - else { - command = rb_check_string_type(*cmd); - if (!NIL_P(command)) { - SafeStringValue(command); /* taint check */ - *cmd = command; - switch (RSTRING_LEN(command)) { - case 0: - goto sig_ign; - break; - case 14: - if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) { - func = SIG_DFL; - *cmd = 0; - } - break; - case 7: - if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) { -sig_ign: - func = SIG_IGN; - *cmd = 0; - } - else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) { -sig_dfl: - func = default_handler(sig); - *cmd = 0; - } - else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) { - goto sig_dfl; - } - break; - case 6: - if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) { - goto sig_ign; - } - break; - case 4: - if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) { - *cmd = Qundef; - } - break; - } - } - else { - rb_proc_t *proc; - GetProcPtr(*cmd, proc); - } - } - - return func; -} - -static int -trap_signm(VALUE vsig) -{ - int sig = -1; - const char *s; - - switch (TYPE(vsig)) { - case T_FIXNUM: - sig = FIX2INT(vsig); - if (sig < 0 || sig >= NSIG) { - rb_raise(rb_eArgError, "invalid signal number (%d)", sig); - } - break; - - case T_SYMBOL: - s = rb_id2name(SYM2ID(vsig)); - if (!s) rb_raise(rb_eArgError, "bad signal"); - goto str_signal; - - default: - s = StringValuePtr(vsig); - - str_signal: - if (strncmp("SIG", s, 3) == 0) - s += 3; - sig = signm2signo(s); - if (sig == 0 && strcmp(s, "EXIT") != 0) - rb_raise(rb_eArgError, "unsupported signal SIG%s", s); - } - return sig; -} - -static VALUE -trap(struct trap_arg *arg) -{ - sighandler_t oldfunc, func = arg->func; - VALUE oldcmd, command = arg->cmd; - int sig = arg->sig; - - oldfunc = ruby_signal(sig, func); - oldcmd = trap_list[sig].cmd; - switch (oldcmd) { - case 0: - if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE"); - else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT"); - else oldcmd = Qnil; - break; - case Qundef: - oldcmd = rb_str_new2("EXIT"); - break; - } - - trap_list[sig].cmd = command; - trap_list[sig].safe = rb_safe_level(); - /* enable at least specified signal. */ -#if USE_TRAP_MASK -#ifdef HAVE_SIGPROCMASK - sigdelset(&arg->mask, sig); -#else - arg->mask &= ~sigmask(sig); -#endif -#endif - return oldcmd; -} - -#if USE_TRAP_MASK -static VALUE -trap_ensure(struct trap_arg *arg) -{ - /* enable interrupt */ -#ifdef HAVE_SIGPROCMASK - sigprocmask(SIG_SETMASK, &arg->mask, NULL); -#else - sigsetmask(arg->mask); -#endif - trap_last_mask = arg->mask; - return 0; -} -#endif - -void -rb_trap_restore_mask(void) -{ -#if USE_TRAP_MASK -# ifdef HAVE_SIGPROCMASK - sigprocmask(SIG_SETMASK, &trap_last_mask, NULL); -# else - sigsetmask(trap_last_mask); -# endif -#endif -} - -/* - * call-seq: - * Signal.trap( signal, command ) => obj - * Signal.trap( signal ) {| | block } => obj - * - * Specifies the handling of signals. The first parameter is a signal - * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a - * signal number. The characters ``SIG'' may be omitted from the - * signal name. The command or block specifies code to be run when the - * signal is raised. - * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal - * will be ignored. - * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler - * will be invoked. - * If the command is ``EXIT'', the script will be terminated by the signal. - * If the command is ``SYSTEM_DEFAULT'', the operating system's default - * handler will be invoked. - * Otherwise, the given command or block will be run. - * The special signal name ``EXIT'' or signal number zero will be - * invoked just prior to program termination. - * trap returns the previous handler for the given signal. - * - * Signal.trap(0, proc { puts "Terminating: #{$$}" }) - * Signal.trap("CLD") { puts "Child died" } - * fork && Process.wait - * - * produces: - * Terminating: 27461 - * Child died - * Terminating: 27460 - */ -static VALUE -sig_trap(int argc, VALUE *argv) -{ - struct trap_arg arg; - - rb_secure(2); - if (argc == 0 || argc > 2) { - rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}"); - } - - arg.sig = trap_signm(argv[0]); - if (argc == 1) { - arg.cmd = rb_block_proc(); - arg.func = sighandler; - } - else if (argc == 2) { - arg.cmd = argv[1]; - arg.func = trap_handler(&arg.cmd, arg.sig); - } - - if (OBJ_TAINTED(arg.cmd)) { - rb_raise(rb_eSecurityError, "Insecure: tainted signal trap"); - } -#if USE_TRAP_MASK - /* disable interrupt */ -# ifdef HAVE_SIGPROCMASK - sigfillset(&arg.mask); - sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask); -# else - arg.mask = sigblock(~0); -# endif - - return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg); -#else - return trap(&arg); -#endif -} - -/* - * call-seq: - * Signal.list => a_hash - * - * Returns a list of signal names mapped to the corresponding - * underlying signal numbers. - * - * 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} - */ -static VALUE -sig_list(void) -{ - VALUE h = rb_hash_new(); - const struct signals *sigs; - - for (sigs = siglist; sigs->signm; sigs++) { - rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo)); - } - return h; -} - -static void -install_sighandler(int signum, sighandler_t handler) -{ - sighandler_t old; - - old = ruby_signal(signum, handler); - if (old != SIG_DFL) { - ruby_signal(signum, old); - } -} - -#if defined(SIGCLD) || defined(SIGCHLD) -static void -init_sigchld(int sig) -{ - sighandler_t oldfunc; -#if USE_TRAP_MASK -# ifdef HAVE_SIGPROCMASK - sigset_t mask; -# else - int mask; -# endif -#endif - -#if USE_TRAP_MASK - /* disable interrupt */ -# ifdef HAVE_SIGPROCMASK - sigfillset(&mask); - sigprocmask(SIG_BLOCK, &mask, &mask); -# else - mask = sigblock(~0); -# endif -#endif - - oldfunc = ruby_signal(sig, SIG_DFL); - if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) { - ruby_signal(sig, oldfunc); - } else { - trap_list[sig].cmd = 0; - } - -#if USE_TRAP_MASK -#ifdef HAVE_SIGPROCMASK - sigdelset(&mask, sig); - sigprocmask(SIG_SETMASK, &mask, NULL); -#else - mask &= ~sigmask(sig); - sigsetmask(mask); -#endif - trap_last_mask = mask; -#endif -} -#endif - -void -ruby_sig_finalize() -{ - sighandler_t oldfunc; - - oldfunc = ruby_signal(SIGINT, SIG_IGN); - if (oldfunc == sighandler) { - ruby_signal(SIGINT, SIG_DFL); - } -} - - -#ifdef RUBY_DEBUG_ENV -int ruby_enable_coredump = 0; -#endif - -/* - * Many operating systems allow signals to be sent to running - * processes. Some signals have a defined effect on the process, while - * others may be trapped at the code level and acted upon. For - * example, your process may trap the USR1 signal and use it to toggle - * debugging, and may use TERM to initiate a controlled shutdown. - * - * pid = fork do - * Signal.trap("USR1") do - * $debug = !$debug - * puts "Debug now: #$debug" - * end - * Signal.trap("TERM") do - * puts "Terminating..." - * shutdown() - * end - * # . . . do some work . . . - * end - * - * Process.detach(pid) - * - * # Controlling program: - * Process.kill("USR1", pid) - * # ... - * Process.kill("USR1", pid) - * # ... - * Process.kill("TERM", pid) - * - * produces: - * Debug now: true - * Debug now: false - * Terminating... - * - * The list of available signal names and their interpretation is - * system dependent. Signal delivery semantics may also vary between - * systems; in particular signal delivery may not always be reliable. - */ -void -Init_signal(void) -{ -#ifndef MACOS_UNUSE_SIGNAL - VALUE mSignal = rb_define_module("Signal"); - - rb_define_global_function("trap", sig_trap, -1); - rb_define_module_function(mSignal, "trap", sig_trap, -1); - rb_define_module_function(mSignal, "list", sig_list, 0); - - rb_define_method(rb_eSignal, "initialize", esignal_init, -1); - rb_define_method(rb_eSignal, "signo", esignal_signo, 0); - rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message")); - rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1); - - install_sighandler(SIGINT, sighandler); -#ifdef SIGHUP - install_sighandler(SIGHUP, sighandler); -#endif -#ifdef SIGQUIT - install_sighandler(SIGQUIT, sighandler); -#endif -#ifdef SIGTERM - install_sighandler(SIGTERM, sighandler); -#endif -#ifdef SIGALRM - install_sighandler(SIGALRM, sighandler); -#endif -#ifdef SIGUSR1 - install_sighandler(SIGUSR1, sighandler); -#endif -#ifdef SIGUSR2 - install_sighandler(SIGUSR2, sighandler); -#endif - -#ifdef RUBY_DEBUG_ENV - if (!ruby_enable_coredump) -#endif - { -#ifdef SIGBUS - install_sighandler(SIGBUS, sigbus); -#endif -#ifdef SIGSEGV - install_sighandler(SIGSEGV, sigsegv); -#endif - } -#ifdef SIGPIPE - install_sighandler(SIGPIPE, sigpipe); -#endif - -#if defined(SIGCLD) - init_sigchld(SIGCLD); -#elif defined(SIGCHLD) - init_sigchld(SIGCHLD); -#endif - -#endif /* MACOS_UNUSE_SIGNAL */ -} |