From 3db12e8b236ac8f88db8eb4690d10e4a3b8dbcd4 Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 16 Jan 1998 12:13:05 +0000 Subject: Initial revision git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- signal.c | 534 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 534 insertions(+) create mode 100644 signal.c (limited to 'signal.c') diff --git a/signal.c b/signal.c new file mode 100644 index 0000000000..e5621b4ec1 --- /dev/null +++ b/signal.c @@ -0,0 +1,534 @@ +/************************************************ + + signal.c - + + $Author$ + $Date$ + created at: Tue Dec 20 10:13:44 JST 1994 + +************************************************/ + +#include "ruby.h" +#include "sig.h" +#include +#include + +#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 + 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; +} + +VALUE +f_kill(argc, argv) + int argc; + VALUE *argv; +{ + int sig; + int i; + char *s; + + rb_secure(2); + if (argc < 2) + ArgError("wrong # of arguments -- kill(sig, pid...)"); + switch (TYPE(argv[0])) { + case T_FIXNUM: + sig = FIX2UINT(argv[0]); + if (sig >= NSIG) { + s = rb_id2name(sig); + if (!s) ArgError("Bad signal"); + goto str_signal; + } + break; + + case T_STRING: + { + int negative = 0; + + 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) + ArgError("Unrecognized signal name `%s'", s); + + if (negative) + sig = -sig; + } + break; + + default: + ArgError("bad signal type %s", rb_class2name(CLASS_OF(argv[0]))); + break; + } + + if (sig < 0) { + sig = -sig; + for (i=1; i= NSIG ||(sig != SIGINT && !trap_list[sig])) + Bug("trap_handler: Bad signal %d", sig); + +#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL) + signal(sig, sighandle); +#endif + + if (trap_immediate) { + trap_immediate = 0; + if (sig == SIGINT && !trap_list[SIGINT]) { +#ifdef THREAD + thread_interrupt(); +#else + rb_interrupt(); +#endif + } + rb_trap_eval(trap_list[sig], sig); + trap_immediate = 1; + } + else { + trap_pending++; + trap_pending_list[sig]++; + } +} + +#ifdef SIGBUS +static RETSIGTYPE +sigbus(sig) + int sig; +{ + Bug("Bus Error"); +} +#endif + +#ifdef SIGSEGV +static RETSIGTYPE +sigsegv(sig) + int sig; +{ + Bug("Segmentation fault"); +} +#endif + +void +rb_trap_exit() +{ + if (trap_list[0]) + rb_eval_cmd(trap_list[0], ary_new3(1, INT2FIX(0))); +} + +void +rb_trap_exec() +{ + int i; + + for (i=0; icmd; + if (NIL_P(command)) { + func = SIG_IGN; + } + else if (TYPE(command) == T_STRING) { + Check_SafeStr(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; + } + + if (TYPE(arg->sig) == T_STRING) { + char *s = RSTRING(arg->sig)->ptr; + + if (strncmp("SIG", s, 3) == 0) + s += 3; + sig = signm2signo(s); + if (sig == 0 && strcmp(s, "EXIT") != 0) + ArgError("Invalid signal SIG%s", s); + } + else { + sig = NUM2INT(arg->sig); + } + if (sig < 0 || sig > NSIG) { + ArgError("Invalid signal no %d", sig); + } +#if defined(THREAD) && defined(HAVE_SETITIMER) && !defined(__BOW__) + if (sig == SIGVTALRM) { + ArgError("SIGVTALRM reserved for Thread; cannot set handler"); + } +#endif + if (func == SIG_DFL) { + switch (sig) { + case SIGINT: + func = sighandle; + break; +#ifdef SIGBUS + case SIGBUS: + func = sigbus; + break; +#endif +#ifdef SIGSEGV + case SIGSEGV: + func = sigsegv; + break; +#endif + } + } +#ifdef POSIX_SIGNAL + posix_signal(sig, func); +#else + signal(sig, func); +#endif + old = trap_list[sig]; + if (!old) old = Qnil; + + trap_list[sig] = command; + /* enable at least specified signal. */ +#ifndef NT +#ifdef HAVE_SIGPROCMASK + sigdelset(&arg->mask, sig); +#else + arg->mask &= ~sigmask(sig); +#endif +#endif + return old; +} + +#ifndef NT +static void +trap_ensure(arg) + struct trap_arg *arg; +{ + /* enable interrupt */ +#ifdef HAVE_SIGPROCMASK + sigprocmask(SIG_SETMASK, &arg->mask, NULL); +#else + sigsetmask(arg->mask); +#endif +} +#endif + +static VALUE +f_trap(argc, argv) + int argc; + VALUE *argv; +{ + struct trap_arg arg; + + rb_secure(2); + if (argc == 0 || argc > 2) { + ArgError("wrong # of arguments -- trap(sig, cmd)/trap(sig){...}"); + } + + arg.sig = argv[0]; + if (argc == 1) { + arg.cmd = f_lambda(); + } + else if (argc == 2) { + arg.cmd = argv[1]; + } + +#ifndef 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, &arg, trap_ensure, &arg); +#else + return trap(&arg); +#endif +} + +void +Init_signal() +{ + extern VALUE mKernel; + + rb_define_global_function("trap", f_trap, -1); +#ifdef POSIX_SIGNAL + posix_signal(SIGINT, sighandle); +#else + signal(SIGINT, sighandle); +#endif +#ifdef SIGBUS + signal(SIGBUS, sigbus); +#endif +#ifdef SIGSEGV + signal(SIGSEGV, sigsegv); +#endif +} -- cgit v1.2.3