Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals

signal.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   signal.c -
00004 
00005   $Author: matz $
00006   $Date: 2005/12/15 15:57:05 $
00007   created at: Tue Dec 20 10:13:44 JST 1994
00008 
00009   Copyright (C) 1993-2003 Yukihiro Matsumoto
00010   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
00011   Copyright (C) 2000  Information-technology Promotion Agency, Japan
00012 
00013 **********************************************************************/
00014 
00015 #include "ruby.h"
00016 #include "rubysig.h"
00017 #include <signal.h>
00018 #include <stdio.h>
00019 
00020 #ifdef __BEOS__
00021 #undef SIGBUS
00022 #endif
00023 
00024 #ifndef NSIG
00025 # ifdef DJGPP
00026 #  define NSIG SIGMAX
00027 # else
00028 #  define NSIG (_SIGMAX + 1)      /* For QNX */
00029 # endif
00030 #endif
00031 
00032 static struct signals {
00033     char *signm;
00034     int  signo;
00035 } siglist [] = {
00036     {"EXIT", 0},
00037 #ifdef SIGHUP
00038     {"HUP", SIGHUP},
00039 #endif
00040     {"INT", SIGINT},
00041 #ifdef SIGQUIT
00042     {"QUIT", SIGQUIT},
00043 #endif
00044 #ifdef SIGILL
00045     {"ILL", SIGILL},
00046 #endif
00047 #ifdef SIGTRAP
00048     {"TRAP", SIGTRAP},
00049 #endif
00050 #ifdef SIGIOT
00051     {"IOT", SIGIOT},
00052 #endif
00053 #ifdef SIGABRT
00054     {"ABRT", SIGABRT},
00055 #endif
00056 #ifdef SIGEMT
00057     {"EMT", SIGEMT},
00058 #endif
00059 #ifdef SIGFPE
00060     {"FPE", SIGFPE},
00061 #endif
00062 #ifdef SIGKILL
00063     {"KILL", SIGKILL},
00064 #endif
00065 #ifdef SIGBUS
00066     {"BUS", SIGBUS},
00067 #endif
00068 #ifdef SIGSEGV
00069     {"SEGV", SIGSEGV},
00070 #endif
00071 #ifdef SIGSYS
00072     {"SYS", SIGSYS},
00073 #endif
00074 #ifdef SIGPIPE
00075     {"PIPE", SIGPIPE},
00076 #endif
00077 #ifdef SIGALRM
00078     {"ALRM", SIGALRM},
00079 #endif
00080 #ifdef SIGTERM
00081     {"TERM", SIGTERM},
00082 #endif
00083 #ifdef SIGURG
00084     {"URG", SIGURG},
00085 #endif
00086 #ifdef SIGSTOP
00087     {"STOP", SIGSTOP},
00088 #endif
00089 #ifdef SIGTSTP
00090     {"TSTP", SIGTSTP},
00091 #endif
00092 #ifdef SIGCONT
00093     {"CONT", SIGCONT},
00094 #endif
00095 #ifdef SIGCHLD
00096     {"CHLD", SIGCHLD},
00097 #endif
00098 #ifdef SIGCLD
00099     {"CLD", SIGCLD},
00100 #else
00101 # ifdef SIGCHLD
00102     {"CLD", SIGCHLD},
00103 # endif
00104 #endif
00105 #ifdef SIGTTIN
00106     {"TTIN", SIGTTIN},
00107 #endif
00108 #ifdef SIGTTOU
00109     {"TTOU", SIGTTOU},
00110 #endif
00111 #ifdef SIGIO
00112     {"IO", SIGIO},
00113 #endif
00114 #ifdef SIGXCPU
00115     {"XCPU", SIGXCPU},
00116 #endif
00117 #ifdef SIGXFSZ
00118     {"XFSZ", SIGXFSZ},
00119 #endif
00120 #ifdef SIGVTALRM
00121     {"VTALRM", SIGVTALRM},
00122 #endif
00123 #ifdef SIGPROF
00124     {"PROF", SIGPROF},
00125 #endif
00126 #ifdef SIGWINCH
00127     {"WINCH", SIGWINCH},
00128 #endif
00129 #ifdef SIGUSR1
00130     {"USR1", SIGUSR1},
00131 #endif
00132 #ifdef SIGUSR2
00133     {"USR2", SIGUSR2},
00134 #endif
00135 #ifdef SIGLOST
00136     {"LOST", SIGLOST},
00137 #endif
00138 #ifdef SIGMSG
00139     {"MSG", SIGMSG},
00140 #endif
00141 #ifdef SIGPWR
00142     {"PWR", SIGPWR},
00143 #endif
00144 #ifdef SIGPOLL
00145     {"POLL", SIGPOLL},
00146 #endif
00147 #ifdef SIGDANGER
00148     {"DANGER", SIGDANGER},
00149 #endif
00150 #ifdef SIGMIGRATE
00151     {"MIGRATE", SIGMIGRATE},
00152 #endif
00153 #ifdef SIGPRE
00154     {"PRE", SIGPRE},
00155 #endif
00156 #ifdef SIGGRANT
00157     {"GRANT", SIGGRANT},
00158 #endif
00159 #ifdef SIGRETRACT
00160     {"RETRACT", SIGRETRACT},
00161 #endif
00162 #ifdef SIGSOUND
00163     {"SOUND", SIGSOUND},
00164 #endif
00165 #ifdef SIGINFO
00166     {"INFO", SIGINFO},
00167 #endif
00168     {NULL, 0}
00169 };
00170 
00171 static int
00172 signm2signo(nm)
00173     char *nm;
00174 {
00175     struct signals *sigs;
00176 
00177     for (sigs = siglist; sigs->signm; sigs++)
00178         if (strcmp(sigs->signm, nm) == 0)
00179             return sigs->signo;
00180     return 0;
00181 }
00182 
00183 static char*
00184 signo2signm(no)
00185     int no;
00186 {
00187     struct signals *sigs;
00188 
00189     for (sigs = siglist; sigs->signm; sigs++)
00190         if (sigs->signo == no)
00191             return sigs->signm;
00192     return 0;
00193 }
00194 
00195 const char *
00196 ruby_signal_name(no)
00197     int no;
00198 {
00199     return signo2signm(no);
00200 }
00201 
00202 /*
00203  *  call-seq:
00204  *     Process.kill(signal, pid, ...)    => fixnum
00205  *  
00206  *  Sends the given signal to the specified process id(s), or to the
00207  *  current process if _pid_ is zero. _signal_ may be an
00208  *  integer signal number or a POSIX signal name (either with or without
00209  *  a +SIG+ prefix). If _signal_ is negative (or starts
00210  *  with a minus sign), kills process groups instead of
00211  *  processes. Not all signals are available on all platforms.
00212  *     
00213  *     pid = fork do
00214  *        Signal.trap("HUP") { puts "Ouch!"; exit }
00215  *        # ... do some work ...
00216  *     end
00217  *     # ...
00218  *     Process.kill("HUP", pid)
00219  *     Process.wait
00220  *     
00221  *  <em>produces:</em>
00222  *     
00223  *     Ouch!
00224  */
00225 
00226 VALUE
00227 rb_f_kill(argc, argv)
00228     int argc;
00229     VALUE *argv;
00230 {
00231     int negative = 0;
00232     int sig;
00233     int i;
00234     char *s;
00235 
00236     rb_secure(2);
00237     if (argc < 2)
00238         rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)");
00239     switch (TYPE(argv[0])) {
00240       case T_FIXNUM:
00241         sig = FIX2INT(argv[0]);
00242         break;
00243 
00244       case T_SYMBOL:
00245         s = rb_id2name(SYM2ID(argv[0]));
00246         if (!s) rb_raise(rb_eArgError, "bad signal");
00247         goto str_signal;
00248 
00249       case T_STRING:
00250         s = RSTRING(argv[0])->ptr;
00251         if (s[0] == '-') {
00252             negative++;
00253             s++;
00254         }
00255       str_signal:
00256         if (strncmp("SIG", s, 3) == 0)
00257             s += 3;
00258         if((sig = signm2signo(s)) == 0)
00259             rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
00260 
00261         if (negative)
00262             sig = -sig;
00263         break;
00264 
00265       default:
00266         {
00267             VALUE str;
00268 
00269             str = rb_check_string_type(argv[0]);
00270             if (!NIL_P(str)) {
00271                 s = RSTRING(str)->ptr;
00272                 goto str_signal;
00273             }
00274             rb_raise(rb_eArgError, "bad signal type %s",
00275                      rb_obj_classname(argv[0]));
00276         }
00277         break;
00278     }
00279 
00280     if (sig < 0) {
00281         sig = -sig;
00282         for (i=1; i<argc; i++) {
00283             int pid = NUM2INT(argv[i]);
00284 #ifdef HAS_KILLPG
00285             if (killpg(pid, sig) < 0)
00286 #else
00287             if (kill(-pid, sig) < 0)
00288 #endif
00289                 rb_sys_fail(0);
00290         }
00291     }
00292     else {
00293         for (i=1; i<argc; i++) {
00294             Check_Type(argv[i], T_FIXNUM);
00295             if (kill(FIX2INT(argv[i]), sig) < 0)
00296                 rb_sys_fail(0);
00297         }
00298     }
00299     return INT2FIX(i-1);
00300 }
00301 
00302 static struct {
00303     VALUE cmd;
00304     int safe;
00305 } trap_list[NSIG];
00306 static rb_atomic_t trap_pending_list[NSIG];
00307 rb_atomic_t rb_trap_pending;
00308 rb_atomic_t rb_trap_immediate;
00309 int rb_prohibit_interrupt = 1;
00310 
00311 void
00312 rb_gc_mark_trap_list()
00313 {
00314 #ifndef MACOS_UNUSE_SIGNAL
00315     int i;
00316 
00317     for (i=0; i<NSIG; i++) {
00318         if (trap_list[i].cmd)
00319             rb_gc_mark(trap_list[i].cmd);
00320     }
00321 #endif /* MACOS_UNUSE_SIGNAL */
00322 }
00323 
00324 #ifdef __dietlibc__
00325 #define sighandler_t sh_t
00326 #endif
00327 
00328 typedef RETSIGTYPE (*sighandler_t)(int);
00329 
00330 #ifdef POSIX_SIGNAL
00331 static sighandler_t
00332 ruby_signal(signum, handler)
00333     int signum;
00334     sighandler_t handler;
00335 {
00336     struct sigaction sigact, old;
00337 
00338     sigact.sa_handler = handler;
00339     sigemptyset(&sigact.sa_mask);
00340     sigact.sa_flags = 0;
00341 #if defined(SA_RESTART)
00342     /* All other signals but VTALRM shall restart restartable syscall
00343        VTALRM will cause EINTR to syscall if interrupted.
00344     */
00345     if (signum != SIGVTALRM) {
00346         sigact.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
00347     }
00348 #endif
00349 #ifdef SA_NOCLDWAIT
00350     if (signum == SIGCHLD && handler == SIG_IGN)
00351         sigact.sa_flags |= SA_NOCLDWAIT;
00352 #endif
00353     sigaction(signum, &sigact, &old);
00354     return old.sa_handler;
00355 }
00356 
00357 void
00358 posix_signal(signum, handler)
00359     int signum;
00360     sighandler_t handler;
00361 {
00362     ruby_signal(signum, handler);
00363 }
00364 #else
00365 #define ruby_signal(sig,handler) signal((sig),(handler))
00366 #endif
00367 
00368 static void signal_exec (int sig);
00369 static void
00370 signal_exec(sig)
00371     int sig;
00372 {
00373     if (trap_list[sig].cmd == 0) {
00374         switch (sig) {
00375           case SIGINT:
00376             rb_thread_interrupt();
00377             break;
00378 #ifdef SIGHUP
00379           case SIGHUP:
00380 #endif
00381 #ifdef SIGQUIT
00382           case SIGQUIT:
00383 #endif
00384 #ifdef SIGALRM
00385           case SIGALRM:
00386 #endif
00387 #ifdef SIGUSR1
00388           case SIGUSR1:
00389 #endif
00390 #ifdef SIGUSR2
00391           case SIGUSR2:
00392 #endif
00393             rb_thread_signal_raise(signo2signm(sig));
00394             break;
00395         }
00396     }
00397     else {
00398         rb_thread_trap_eval(trap_list[sig].cmd, sig, trap_list[sig].safe);
00399     }
00400 }
00401 
00402 static RETSIGTYPE sighandler (int);
00403 static RETSIGTYPE
00404 sighandler(sig)
00405     int sig;
00406 {
00407 #ifdef _WIN32
00408 #define IN_MAIN_CONTEXT(f, a) (rb_w32_main_context(a, f) ? (void)0 : f(a))
00409 #else
00410 #define IN_MAIN_CONTEXT(f, a) f(a)
00411 #endif
00412 
00413     if (sig >= NSIG) {
00414         rb_bug("trap_handler: Bad signal %d", sig);
00415     }
00416 
00417 #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
00418     ruby_signal(sig, sighandler);
00419 #endif
00420 
00421     if (ATOMIC_TEST(rb_trap_immediate)) {
00422         IN_MAIN_CONTEXT(signal_exec, sig);
00423         ATOMIC_SET(rb_trap_immediate, 1);
00424     }
00425     else {
00426         ATOMIC_INC(rb_trap_pending);
00427         ATOMIC_INC(trap_pending_list[sig]);
00428     }
00429 }
00430 
00431 #ifdef SIGBUS
00432 static RETSIGTYPE sigbus (int);
00433 static RETSIGTYPE
00434 sigbus(sig)
00435     int sig;
00436 {
00437     rb_bug("Bus Error");
00438 }
00439 #endif
00440 
00441 #ifdef SIGSEGV
00442 static RETSIGTYPE sigsegv (int);
00443 static RETSIGTYPE
00444 sigsegv(sig)
00445     int sig;
00446 {
00447     rb_bug("Segmentation fault");
00448 }
00449 #endif
00450 
00451 #ifdef SIGPIPE
00452 static RETSIGTYPE sigpipe (int);
00453 static RETSIGTYPE
00454 sigpipe(sig)
00455     int sig;
00456 {
00457     /* do nothing */
00458 }
00459 #endif
00460 
00461 void
00462 rb_trap_exit()
00463 {
00464 #ifndef MACOS_UNUSE_SIGNAL
00465     if (trap_list[0].cmd) {
00466         VALUE trap_exit = trap_list[0].cmd;
00467 
00468         trap_list[0].cmd = 0;
00469         rb_eval_cmd(trap_exit, rb_ary_new3(1, INT2FIX(0)), trap_list[0].safe);
00470     }
00471 #endif
00472 }
00473 
00474 void
00475 rb_trap_exec()
00476 {
00477 #ifndef MACOS_UNUSE_SIGNAL
00478     int i;
00479 
00480     for (i=0; i<NSIG; i++) {
00481         if (trap_pending_list[i]) {
00482             trap_pending_list[i] = 0;
00483             signal_exec(i);
00484         }
00485     }
00486 #endif /* MACOS_UNUSE_SIGNAL */
00487     rb_trap_pending = 0;
00488 }
00489 
00490 struct trap_arg {
00491 #ifndef _WIN32
00492 # ifdef HAVE_SIGPROCMASK
00493     sigset_t mask;
00494 # else
00495     int mask;
00496 # endif
00497 #endif
00498     VALUE sig, cmd;
00499 };
00500 
00501 # ifdef HAVE_SIGPROCMASK
00502 static sigset_t trap_last_mask;
00503 # else
00504 static int trap_last_mask;
00505 # endif
00506 
00507 static RETSIGTYPE sigexit (int);
00508 static RETSIGTYPE
00509 sigexit(sig)
00510     int sig;
00511 {
00512     rb_thread_signal_exit();
00513 }
00514 
00515 static VALUE
00516 trap(arg)
00517     struct trap_arg *arg;
00518 {
00519     sighandler_t func, oldfunc;
00520     VALUE command, oldcmd;
00521     int sig = -1;
00522     char *s;
00523 
00524     func = sighandler;
00525     command = arg->cmd;
00526     if (NIL_P(command)) {
00527         func = SIG_IGN;
00528     }
00529     else if (TYPE(command) == T_STRING) {
00530         SafeStringValue(command);       /* taint check */
00531         if (RSTRING(command)->len == 0) {
00532             func = SIG_IGN;
00533         }
00534         else if (RSTRING(command)->len == 7) {
00535             if (strncmp(RSTRING(command)->ptr, "SIG_IGN", 7) == 0) {
00536                 func = SIG_IGN;
00537             }
00538             else if (strncmp(RSTRING(command)->ptr, "SIG_DFL", 7) == 0) {
00539                 func = SIG_DFL;
00540             }
00541             else if (strncmp(RSTRING(command)->ptr, "DEFAULT", 7) == 0) {
00542                 func = SIG_DFL;
00543             }
00544         }
00545         else if (RSTRING(command)->len == 6) {
00546             if (strncmp(RSTRING(command)->ptr, "IGNORE", 6) == 0) {
00547                 func = SIG_IGN;
00548             }
00549         }
00550         else if (RSTRING(command)->len == 4) {
00551             if (strncmp(RSTRING(command)->ptr, "EXIT", 4) == 0) {
00552                 func = sigexit;
00553             }
00554         }
00555     }
00556     if (func == SIG_IGN || func == SIG_DFL) {
00557         command = 0;
00558     }
00559 
00560     switch (TYPE(arg->sig)) {
00561       case T_FIXNUM:
00562         sig = FIX2INT(arg->sig);
00563         break;
00564 
00565       case T_SYMBOL:
00566         s = rb_id2name(SYM2ID(arg->sig));
00567         if (!s) rb_raise(rb_eArgError, "bad signal");
00568         goto str_signal;
00569 
00570       case T_STRING:
00571         s = RSTRING(arg->sig)->ptr;
00572 
00573       str_signal:
00574         if (strncmp("SIG", s, 3) == 0)
00575             s += 3;
00576         sig = signm2signo(s);
00577         if (sig == 0 && strcmp(s, "EXIT") != 0)
00578             rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
00579     }
00580 
00581     if (sig < 0 || sig > NSIG) {
00582         rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
00583     }
00584 #if defined(HAVE_SETITIMER)
00585     if (sig == SIGVTALRM) {
00586         rb_raise(rb_eArgError, "SIGVTALRM reserved for Thread; can't set handler");
00587     }
00588 #endif
00589     if (func == SIG_DFL) {
00590         switch (sig) {
00591           case SIGINT:
00592 #ifdef SIGHUP
00593           case SIGHUP:
00594 #endif
00595 #ifdef SIGQUIT
00596           case SIGQUIT:
00597 #endif
00598 #ifdef SIGALRM
00599           case SIGALRM:
00600 #endif
00601 #ifdef SIGUSR1
00602           case SIGUSR1:
00603 #endif
00604 #ifdef SIGUSR2
00605           case SIGUSR2:
00606 #endif
00607             func = sighandler;
00608             break;
00609 #ifdef SIGBUS
00610           case SIGBUS:
00611             func = sigbus;
00612             break;
00613 #endif
00614 #ifdef SIGSEGV
00615           case SIGSEGV:
00616             func = sigsegv;
00617             break;
00618 #endif
00619 #ifdef SIGPIPE
00620           case SIGPIPE:
00621             func = sigpipe;
00622             break;
00623 #endif
00624         }
00625     }
00626     oldfunc = ruby_signal(sig, func);
00627     oldcmd = trap_list[sig].cmd;
00628     if (!oldcmd) {
00629         if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
00630         else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
00631         else oldcmd = Qnil;
00632     }
00633 
00634     trap_list[sig].cmd = command;
00635     trap_list[sig].safe = ruby_safe_level;
00636     /* enable at least specified signal. */
00637 #ifndef _WIN32
00638 #ifdef HAVE_SIGPROCMASK
00639     sigdelset(&arg->mask, sig);
00640 #else
00641     arg->mask &= ~sigmask(sig);
00642 #endif
00643 #endif
00644     return oldcmd;
00645 }
00646 
00647 #ifndef _WIN32
00648 static VALUE
00649 trap_ensure(arg)
00650     struct trap_arg *arg;
00651 {
00652     /* enable interrupt */
00653 #ifdef HAVE_SIGPROCMASK
00654     sigprocmask(SIG_SETMASK, &arg->mask, NULL);
00655 #else
00656     sigsetmask(arg->mask);
00657 #endif
00658     trap_last_mask = arg->mask;
00659     return 0;
00660 }
00661 #endif
00662 
00663 void
00664 rb_trap_restore_mask()
00665 {
00666 #ifndef _WIN32
00667 # ifdef HAVE_SIGPROCMASK
00668     sigprocmask(SIG_SETMASK, &trap_last_mask, NULL);
00669 # else
00670     sigsetmask(trap_last_mask);
00671 # endif
00672 #endif
00673 }
00674 
00675 /*
00676  * call-seq:
00677  *   Signal.trap( signal, proc ) => obj
00678  *   Signal.trap( signal ) {| | block } => obj
00679  *
00680  * Specifies the handling of signals. The first parameter is a signal
00681  * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
00682  * signal number. The characters ``SIG'' may be omitted from the
00683  * signal name. The command or block specifies code to be run when the
00684  * signal is raised. If the command is the string ``IGNORE'' or
00685  * ``SIG_IGN'', the signal will be ignored. If the command is
00686  * ``DEFAULT'' or ``SIG_DFL'', the operating system's default handler
00687  * will be invoked. If the command is ``EXIT'', the script will be
00688  * terminated by the signal. Otherwise, the given command or block
00689  * will be run.
00690  * The special signal name ``EXIT'' or signal number zero will be
00691  * invoked just prior to program termination.
00692  * trap returns the previous handler for the given signal.
00693  *
00694  *     Signal.trap(0, proc { puts "Terminating: #{$$}" })
00695  *     Signal.trap("CLD")  { puts "Child died" }
00696  *     fork && Process.wait
00697  *
00698  * produces:
00699  *     Terminating: 27461
00700  *     Child died
00701  *     Terminating: 27460
00702  */
00703 static VALUE
00704 sig_trap(argc, argv)
00705     int argc;
00706     VALUE *argv;
00707 {
00708     struct trap_arg arg;
00709 
00710     rb_secure(2);
00711     if (argc == 0 || argc > 2) {
00712         rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
00713     }
00714 
00715     arg.sig = argv[0];
00716     if (argc == 1) {
00717         arg.cmd = rb_block_proc();
00718     }
00719     else if (argc == 2) {
00720         arg.cmd = argv[1];
00721     }
00722 
00723     if (OBJ_TAINTED(arg.cmd)) {
00724         rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
00725     }
00726 #ifndef _WIN32
00727     /* disable interrupt */
00728 # ifdef HAVE_SIGPROCMASK
00729     sigfillset(&arg.mask);
00730     sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask);
00731 # else
00732     arg.mask = sigblock(~0);
00733 # endif
00734 
00735     return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
00736 #else
00737     return trap(&arg);
00738 #endif
00739 }
00740 
00741 /*
00742  * call-seq:
00743  *   Signal.list => a_hash
00744  *
00745  * Returns a list of signal names mapped to the corresponding
00746  * underlying signal numbers.
00747  *
00748  * Signal.list   #=> {"ABRT"=>6, "ALRM"=>14, "BUS"=>7, "CHLD"=>17, "CLD"=>17, "CONT"=>18, "FPE"=>8, "HUP"=>1, "ILL"=>4, "INT"=>2, "IO"=>29, "IOT"=>6, "KILL"=>9, "PIPE"=>13, "POLL"=>29, "PROF"=>27, "PWR"=>30, "QUIT"=>3, "SEGV"=>11, "STOP"=>19, "SYS"=>31, "TERM"=>15, "TRAP"=>5, "TSTP"=>20, "TTIN"=>21, "TTOU"=>22, "URG"=>23, "USR1"=>10, "USR2"=>12, "VTALRM"=>26, "WINCH"=>28, "XCPU"=>24, "XFSZ"=>25}
00749  */
00750 static VALUE
00751 sig_list()
00752 {
00753     VALUE h = rb_hash_new();
00754     struct signals *sigs;
00755 
00756     for (sigs = siglist; sigs->signm; sigs++) {
00757         rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
00758     }
00759     return h;
00760 }
00761 
00762 static void
00763 install_sighandler(signum, handler)
00764     int signum;
00765     sighandler_t handler;
00766 {
00767     sighandler_t old;
00768 
00769     old = ruby_signal(signum, handler);
00770     if (old != SIG_DFL) {
00771         ruby_signal(signum, old);
00772     }
00773 }
00774 
00775 static void
00776 init_sigchld(sig)
00777     int sig;
00778 {
00779     sighandler_t oldfunc;
00780 #ifndef _WIN32
00781 # ifdef HAVE_SIGPROCMASK
00782     sigset_t mask;
00783 # else
00784     int mask;
00785 # endif
00786 #endif
00787 
00788 #ifndef _WIN32
00789     /* disable interrupt */
00790 # ifdef HAVE_SIGPROCMASK
00791     sigfillset(&mask);
00792     sigprocmask(SIG_BLOCK, &mask, &mask);
00793 # else
00794     mask = sigblock(~0);
00795 # endif
00796 #endif
00797 
00798     oldfunc = ruby_signal(sig, SIG_DFL);
00799     if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
00800         ruby_signal(sig, oldfunc);
00801     } else {
00802         trap_list[sig].cmd = 0;
00803     }
00804 
00805 #ifndef _WIN32
00806 #ifdef HAVE_SIGPROCMASK
00807     sigdelset(&mask, sig);
00808     sigprocmask(SIG_SETMASK, &mask, NULL);
00809 #else
00810     mask &= ~sigmask(sig);
00811     sigsetmask(mask);
00812 #endif
00813     trap_last_mask = mask;
00814 #endif
00815 }
00816 
00817 /*
00818  * Many operating systems allow signals to be sent to running
00819  * processes. Some signals have a defined effect on the process, while
00820  * others may be trapped at the code level and acted upon. For
00821  * example, your process may trap the USR1 signal and use it to toggle
00822  * debugging, and may use TERM to initiate a controlled shutdown.
00823  *
00824  *     pid = fork do
00825  *       Signal.trap("USR1") do
00826  *         $debug = !$debug
00827  *         puts "Debug now: #$debug"
00828  *       end
00829  *       Signal.trap("TERM") do
00830  *         puts "Terminating..."
00831  *         shutdown()
00832  *       end
00833  *       # . . . do some work . . .
00834  *     end
00835  *
00836  *     Process.detach(pid)
00837  *
00838  *     # Controlling program:
00839  *     Process.kill("USR1", pid)
00840  *     # ...
00841  *     Process.kill("USR1", pid)
00842  *     # ...
00843  *     Process.kill("TERM", pid)
00844  *
00845  * produces:
00846  *     Debug now: true
00847  *     Debug now: false
00848  *    Terminating...
00849  *
00850  * The list of available signal names and their interpretation is
00851  * system dependent. Signal delivery semantics may also vary between
00852  * systems; in particular signal delivery may not always be reliable.
00853  */
00854 void
00855 Init_signal()
00856 {
00857 #ifndef MACOS_UNUSE_SIGNAL
00858     VALUE mSignal = rb_define_module("Signal");
00859 
00860     rb_define_global_function("trap", sig_trap, -1);
00861     rb_define_module_function(mSignal, "trap", sig_trap, -1);
00862     rb_define_module_function(mSignal, "list", sig_list, 0);
00863 
00864     install_sighandler(SIGINT, sighandler);
00865 #ifdef SIGHUP
00866     install_sighandler(SIGHUP, sighandler);
00867 #endif
00868 #ifdef SIGQUIT
00869     install_sighandler(SIGQUIT, sighandler);
00870 #endif
00871 #ifdef SIGALRM
00872     install_sighandler(SIGALRM, sighandler);
00873 #endif
00874 #ifdef SIGUSR1
00875     install_sighandler(SIGUSR1, sighandler);
00876 #endif
00877 #ifdef SIGUSR2
00878     install_sighandler(SIGUSR2, sighandler);
00879 #endif
00880 
00881 #ifdef SIGBUS
00882     install_sighandler(SIGBUS, sigbus);
00883 #endif
00884 #ifdef SIGSEGV
00885     install_sighandler(SIGSEGV, sigsegv);
00886 #endif
00887 #ifdef SIGPIPE
00888     install_sighandler(SIGPIPE, sigpipe);
00889 #endif
00890 
00891 #ifdef SIGCLD
00892     init_sigchld(SIGCLD);
00893 #endif
00894 #ifdef SIGCHLD
00895     init_sigchld(SIGCHLD);
00896 #endif
00897 
00898 #endif /* MACOS_UNUSE_SIGNAL */
00899 }
00900 

Generated on Wed Jan 18 23:32:06 2006 for Ruby by doxygen 1.3.5