diff options
Diffstat (limited to 'signal.c')
-rw-r--r-- | signal.c | 733 |
1 files changed, 0 insertions, 733 deletions
diff --git a/signal.c b/signal.c deleted file mode 100644 index c643fd48c2..0000000000 --- a/signal.c +++ /dev/null @@ -1,733 +0,0 @@ -/********************************************************************** - - signal.c - - - $Author$ - $Date$ - created at: Tue Dec 20 10:13:44 JST 1994 - - Copyright (C) 1993-2001 Yukihiro Matsumoto - Copyright (C) 2000 Network Applied Communication Laboratory, Inc. - Copyright (C) 2000 Information-technology Promotion Agency, Japan - -**********************************************************************/ - -#include "ruby.h" -#include "rubysig.h" -#include <signal.h> -#include <stdio.h> - -#ifdef __BEOS__ -#undef SIGBUS -#endif - -#ifndef NSIG -# ifdef DJGPP -# define NSIG SIGMAX -# else -# define NSIG (_SIGMAX + 1) /* For QNX */ -# endif -#endif - -static struct signals { - char *signm; - int signo; -} siglist [] = { -#ifdef SIGHUP - "HUP", SIGHUP, -#endif -#ifdef SIGINT - "INT", SIGINT, -#endif -#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(nm) - char *nm; -{ - struct signals *sigs; - - for (sigs = siglist; sigs->signm; sigs++) - if (strcmp(sigs->signm, nm) == 0) - return sigs->signo; - return 0; -} - -static char* -signo2signm(no) - int no; -{ - struct signals *sigs; - - for (sigs = siglist; sigs->signm; sigs++) - if (sigs->signo == no) - return sigs->signm; - return 0; -} - -VALUE -rb_f_kill(argc, argv) - int argc; - VALUE *argv; -{ - int negative = 0; - int sig; - int i; - 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(argv[0])->ptr; - 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_convert_type(argv[0], T_STRING, "String", "to_str"); - if (!NIL_P(str)) { - s = RSTRING(str)->ptr; - goto str_signal; - } - rb_raise(rb_eArgError, "bad signal type %s", - rb_class2name(CLASS_OF(argv[0]))); - } - break; - } - - if (sig < 0) { - sig = -sig; - for (i=1; i<argc; i++) { - int pid = NUM2INT(argv[i]); -#ifdef HAS_KILLPG - if (killpg(pid, sig) < 0) -#else - if (kill(-pid, sig) < 0) -#endif - rb_sys_fail(0); - } - } - else { - for (i=1; i<argc; i++) { - Check_Type(argv[i], T_FIXNUM); - if (kill(FIX2INT(argv[i]), sig) < 0) - rb_sys_fail(0); - } - } - return INT2FIX(i-1); -} - -static VALUE trap_list[NSIG]; -static rb_atomic_t trap_pending_list[NSIG]; -rb_atomic_t rb_trap_pending; -rb_atomic_t rb_trap_immediate; -int rb_prohibit_interrupt; - -void -rb_gc_mark_trap_list() -{ -#ifndef MACOS_UNUSE_SIGNAL - int i; - - for (i=0; i<NSIG; i++) { - if (trap_list[i]) - rb_gc_mark(trap_list[i]); - } -#endif /* MACOS_UNUSE_SIGNAL */ -} - -typedef RETSIGTYPE (*sighandler_t)_((int)); - -#ifdef POSIX_SIGNAL -static sighandler_t -ruby_signal(signum, handler) - int signum; - sighandler_t handler; -{ - struct sigaction sigact, old; - - sigact.sa_handler = handler; - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; -#if defined(SA_RESTART) - /* All other signals but VTALRM shall restart restartable syscall - VTALRM will cause EINTR to syscall if interrupted. - */ - if (signum != SIGVTALRM) { - sigact.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */ - } -#endif -#ifdef SA_NOCLDWAIT - if (signum == SIGCHLD && handler == SIG_IGN) - sigact.sa_flags |= SA_NOCLDWAIT; -#endif - sigaction(signum, &sigact, &old); - return old.sa_handler; -} - -void -posix_signal(signum, handler) - int signum; - sighandler_t handler; -{ - ruby_signal(signum, handler); -} -#else -#define ruby_signal(sig,handler) signal((sig),(handler)) -#endif - -static void signal_exec _((int sig)); -static void -signal_exec(sig) - int sig; -{ - if (trap_list[sig] == 0) { - switch (sig) { - case SIGINT: - rb_thread_interrupt(); - break; -#ifdef SIGHUP - case SIGHUP: -#endif -#ifdef SIGQUIT - case SIGQUIT: -#endif -#ifdef SIGALRM - case SIGALRM: -#endif -#ifdef SIGUSR1 - case SIGUSR1: -#endif -#ifdef SIGUSR2 - case SIGUSR2: -#endif - rb_thread_signal_raise(signo2signm(sig)); - break; - } - } - else { - rb_thread_trap_eval(trap_list[sig], sig); - } -} - -static RETSIGTYPE sighandler _((int)); -static RETSIGTYPE -sighandler(sig) - int sig; -{ -#ifdef NT -#define IN_MAIN_CONTEXT(f, a) (win32_main_context(a, f) ? (void)0 : f(a)) -#else -#define IN_MAIN_CONTEXT(f, a) f(a) -#endif - - if (sig >= NSIG) { - rb_bug("trap_handler: Bad signal %d", sig); - } - -#if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL) - ruby_signal(sig, sighandler); -#endif - - if (ATOMIC_TEST(rb_trap_immediate)) { - IN_MAIN_CONTEXT(signal_exec, sig); - ATOMIC_SET(rb_trap_immediate, 1); - } - else { - ATOMIC_INC(rb_trap_pending); - ATOMIC_INC(trap_pending_list[sig]); - } -} - -#ifdef SIGBUS -static RETSIGTYPE sigbus _((int)); -static RETSIGTYPE -sigbus(sig) - int sig; -{ - rb_bug("Bus Error"); -} -#endif - -#ifdef SIGSEGV -static RETSIGTYPE sigsegv _((int)); -static RETSIGTYPE -sigsegv(sig) - int sig; -{ - rb_bug("Segmentation fault"); -} -#endif - -#ifdef SIGPIPE -static RETSIGTYPE sigpipe _((int)); -static RETSIGTYPE -sigpipe(sig) - int sig; -{ - /* do nothing */ -} -#endif - -void -rb_trap_exit() -{ -#ifndef MACOS_UNUSE_SIGNAL - if (trap_list[0]) { - VALUE trap_exit = trap_list[0]; - - trap_list[0] = 0; - rb_eval_cmd(trap_exit, rb_ary_new3(1, INT2FIX(0)), 0); - } -#endif -} - -void -rb_trap_exec() -{ -#ifndef MACOS_UNUSE_SIGNAL - int i; - - for (i=0; i<NSIG; i++) { - if (trap_pending_list[i]) { - trap_pending_list[i] = 0; - signal_exec(i); - } - } -#endif /* MACOS_UNUSE_SIGNAL */ - rb_trap_pending = 0; -} - -struct trap_arg { -#if !defined(NT) -# ifdef HAVE_SIGPROCMASK - sigset_t mask; -# else - int mask; -# endif -#endif - VALUE sig, cmd; -}; - -# ifdef HAVE_SIGPROCMASK -static sigset_t trap_last_mask; -# else -static int trap_last_mask; -# endif - -static RETSIGTYPE sigexit _((int)); -static RETSIGTYPE -sigexit(sig) - int sig; -{ - rb_exit(0); -} - -static VALUE -trap(arg) - struct trap_arg *arg; -{ - sighandler_t func; - VALUE command, old; - int sig; - char *s; - - func = sighandler; - command = arg->cmd; - if (NIL_P(command)) { - func = SIG_IGN; - } - else if (TYPE(command) == T_STRING) { - SafeStringValue(command); /* taint check */ - if (RSTRING(command)->len == 0) { - func = SIG_IGN; - } - else if (RSTRING(command)->len == 7) { - if (strncmp(RSTRING(command)->ptr, "SIG_IGN", 7) == 0) { - func = SIG_IGN; - } - else if (strncmp(RSTRING(command)->ptr, "SIG_DFL", 7) == 0) { - func = SIG_DFL; - } - else if (strncmp(RSTRING(command)->ptr, "DEFAULT", 7) == 0) { - func = SIG_DFL; - } - } - else if (RSTRING(command)->len == 6) { - if (strncmp(RSTRING(command)->ptr, "IGNORE", 6) == 0) { - func = SIG_IGN; - } - } - else if (RSTRING(command)->len == 4) { - if (strncmp(RSTRING(command)->ptr, "EXIT", 4) == 0) { - func = sigexit; - } - } - } - if (func == SIG_IGN || func == SIG_DFL) { - command = 0; - } - - switch (TYPE(arg->sig)) { - case T_FIXNUM: - sig = NUM2INT(arg->sig); - break; - - case T_SYMBOL: - s = rb_id2name(SYM2ID(arg->sig)); - if (!s) rb_raise(rb_eArgError, "bad signal"); - goto str_signal; - - case T_STRING: - s = RSTRING(arg->sig)->ptr; - - 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); - } - - if (sig < 0 || sig > NSIG) { - rb_raise(rb_eArgError, "invalid signal number (%d)", sig); - } -#if defined(HAVE_SETITIMER) && !defined(__BOW__) - if (sig == SIGVTALRM) { - rb_raise(rb_eArgError, "SIGVTALRM reserved for Thread; cannot set handler"); - } -#endif - if (func == SIG_DFL) { - switch (sig) { - case SIGINT: -#ifdef SIGHUP - case SIGHUP: -#endif -#ifdef SIGQUIT - case SIGQUIT: -#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 - } - } - ruby_signal(sig, func); - old = trap_list[sig]; - if (!old) old = Qnil; - - trap_list[sig] = command; - /* enable at least specified signal. */ -#if !defined(NT) -#ifdef HAVE_SIGPROCMASK - sigdelset(&arg->mask, sig); -#else - arg->mask &= ~sigmask(sig); -#endif -#endif - return old; -} - -#if !defined(NT) -static VALUE -trap_ensure(arg) - 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() -{ -#if !defined(NT) -# ifdef HAVE_SIGPROCMASK - sigprocmask(SIG_SETMASK, &trap_last_mask, NULL); -# else - sigsetmask(trap_last_mask); -# endif -#endif -} - -static VALUE -sig_trap(argc, argv) - 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 = argv[0]; - if (argc == 1) { - arg.cmd = rb_f_lambda(); - } - else if (argc == 2) { - arg.cmd = argv[1]; - } - - if (OBJ_TAINTED(arg.cmd)) { - rb_raise(rb_eSecurityError, "Insecure: tainted signal trap"); - } -#if !defined(NT) - /* 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 -} - -static VALUE -sig_list() -{ - VALUE h = rb_hash_new(); - 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(signum, handler) - int signum; - sighandler_t handler; -{ - sighandler_t old; - - old = ruby_signal(signum, handler); - if (old != SIG_DFL) { - ruby_signal(signum, old); - } -} - -void -Init_signal() -{ -#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); - - install_sighandler(SIGINT, sighandler); -#ifdef SIGHUP - install_sighandler(SIGHUP, sighandler); -#endif -#ifdef SIGQUIT - install_sighandler(SIGQUIT, sighandler); -#endif -#ifdef SIGALRM - install_sighandler(SIGALRM, sighandler); -#endif -#ifdef SIGUSR1 - install_sighandler(SIGUSR1, sighandler); -#endif -#ifdef SIGUSR2 - install_sighandler(SIGUSR2, sighandler); -#endif - -#ifdef SIGBUS - install_sighandler(SIGBUS, sigbus); -#endif -#ifdef SIGSEGV - install_sighandler(SIGSEGV, sigsegv); -#endif -#ifdef SIGPIPE - install_sighandler(SIGPIPE, sigpipe); -#endif -#endif /* MACOS_UNUSE_SIGNAL */ -} |