* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / signal.c
blobb110e16cb7b227f160301663fb66dd5da6285f63
1 /**********************************************************************
3 signal.c -
5 $Author$
6 created at: Tue Dec 20 10:13:44 JST 1994
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "ruby/ruby.h"
15 #include "ruby/signal.h"
16 #include "ruby/node.h"
17 #include "vm_core.h"
18 #include <signal.h>
19 #include <stdio.h>
21 #ifdef __BEOS__
22 #undef SIGBUS
23 #endif
25 #if defined HAVE_SIGPROCMASK || defined HAVE_SIGSETMASK
26 #define USE_TRAP_MASK 1
27 #else
28 #define USE_TRAP_MASK 0
29 #endif
31 #ifndef NSIG
32 # ifdef DJGPP
33 # define NSIG SIGMAX
34 # else
35 # define NSIG (_SIGMAX + 1) /* For QNX */
36 # endif
37 #endif
39 static const struct signals {
40 const char *signm;
41 int signo;
42 } siglist [] = {
43 {"EXIT", 0},
44 #ifdef SIGHUP
45 {"HUP", SIGHUP},
46 #endif
47 {"INT", SIGINT},
48 #ifdef SIGQUIT
49 {"QUIT", SIGQUIT},
50 #endif
51 #ifdef SIGILL
52 {"ILL", SIGILL},
53 #endif
54 #ifdef SIGTRAP
55 {"TRAP", SIGTRAP},
56 #endif
57 #ifdef SIGIOT
58 {"IOT", SIGIOT},
59 #endif
60 #ifdef SIGABRT
61 {"ABRT", SIGABRT},
62 #endif
63 #ifdef SIGEMT
64 {"EMT", SIGEMT},
65 #endif
66 #ifdef SIGFPE
67 {"FPE", SIGFPE},
68 #endif
69 #ifdef SIGKILL
70 {"KILL", SIGKILL},
71 #endif
72 #ifdef SIGBUS
73 {"BUS", SIGBUS},
74 #endif
75 #ifdef SIGSEGV
76 {"SEGV", SIGSEGV},
77 #endif
78 #ifdef SIGSYS
79 {"SYS", SIGSYS},
80 #endif
81 #ifdef SIGPIPE
82 {"PIPE", SIGPIPE},
83 #endif
84 #ifdef SIGALRM
85 {"ALRM", SIGALRM},
86 #endif
87 #ifdef SIGTERM
88 {"TERM", SIGTERM},
89 #endif
90 #ifdef SIGURG
91 {"URG", SIGURG},
92 #endif
93 #ifdef SIGSTOP
94 {"STOP", SIGSTOP},
95 #endif
96 #ifdef SIGTSTP
97 {"TSTP", SIGTSTP},
98 #endif
99 #ifdef SIGCONT
100 {"CONT", SIGCONT},
101 #endif
102 #ifdef SIGCHLD
103 {"CHLD", SIGCHLD},
104 #endif
105 #ifdef SIGCLD
106 {"CLD", SIGCLD},
107 #else
108 # ifdef SIGCHLD
109 {"CLD", SIGCHLD},
110 # endif
111 #endif
112 #ifdef SIGTTIN
113 {"TTIN", SIGTTIN},
114 #endif
115 #ifdef SIGTTOU
116 {"TTOU", SIGTTOU},
117 #endif
118 #ifdef SIGIO
119 {"IO", SIGIO},
120 #endif
121 #ifdef SIGXCPU
122 {"XCPU", SIGXCPU},
123 #endif
124 #ifdef SIGXFSZ
125 {"XFSZ", SIGXFSZ},
126 #endif
127 #ifdef SIGVTALRM
128 {"VTALRM", SIGVTALRM},
129 #endif
130 #ifdef SIGPROF
131 {"PROF", SIGPROF},
132 #endif
133 #ifdef SIGWINCH
134 {"WINCH", SIGWINCH},
135 #endif
136 #ifdef SIGUSR1
137 {"USR1", SIGUSR1},
138 #endif
139 #ifdef SIGUSR2
140 {"USR2", SIGUSR2},
141 #endif
142 #ifdef SIGLOST
143 {"LOST", SIGLOST},
144 #endif
145 #ifdef SIGMSG
146 {"MSG", SIGMSG},
147 #endif
148 #ifdef SIGPWR
149 {"PWR", SIGPWR},
150 #endif
151 #ifdef SIGPOLL
152 {"POLL", SIGPOLL},
153 #endif
154 #ifdef SIGDANGER
155 {"DANGER", SIGDANGER},
156 #endif
157 #ifdef SIGMIGRATE
158 {"MIGRATE", SIGMIGRATE},
159 #endif
160 #ifdef SIGPRE
161 {"PRE", SIGPRE},
162 #endif
163 #ifdef SIGGRANT
164 {"GRANT", SIGGRANT},
165 #endif
166 #ifdef SIGRETRACT
167 {"RETRACT", SIGRETRACT},
168 #endif
169 #ifdef SIGSOUND
170 {"SOUND", SIGSOUND},
171 #endif
172 #ifdef SIGINFO
173 {"INFO", SIGINFO},
174 #endif
175 {NULL, 0}
178 static int
179 signm2signo(const char *nm)
181 const struct signals *sigs;
183 for (sigs = siglist; sigs->signm; sigs++)
184 if (strcmp(sigs->signm, nm) == 0)
185 return sigs->signo;
186 return 0;
189 static const char*
190 signo2signm(int no)
192 const struct signals *sigs;
194 for (sigs = siglist; sigs->signm; sigs++)
195 if (sigs->signo == no)
196 return sigs->signm;
197 return 0;
200 const char *
201 ruby_signal_name(int no)
203 return signo2signm(no);
207 * call-seq:
208 * SignalException.new(sig) => signal_exception
210 * Construct a new SignalException object. +sig+ should be a known
211 * signal name, or a signal number.
214 static VALUE
215 esignal_init(int argc, VALUE *argv, VALUE self)
217 int argnum = 1;
218 VALUE sig = Qnil;
219 int signo;
220 const char *signm;
222 if (argc > 0) {
223 sig = rb_check_to_integer(argv[0], "to_int");
224 if (!NIL_P(sig)) argnum = 2;
225 else sig = argv[0];
227 if (argc < 1 || argnum < argc) {
228 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
229 argc, argnum);
231 if (argnum == 2) {
232 signo = NUM2INT(sig);
233 if (signo < 0 || signo > NSIG) {
234 rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
236 if (argc > 1) {
237 sig = argv[1];
239 else {
240 signm = signo2signm(signo);
241 if (signm) {
242 sig = rb_sprintf("SIG%s", signm);
244 else {
245 sig = rb_sprintf("SIG%u", signo);
249 else {
250 signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig);
251 if (strncmp(signm, "SIG", 3) == 0) signm += 3;
252 signo = signm2signo(signm);
253 if (!signo) {
254 rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
256 sig = rb_sprintf("SIG%s", signm);
258 rb_call_super(1, &sig);
259 rb_iv_set(self, "signo", INT2NUM(signo));
261 return self;
265 * call-seq:
266 * signal_exception.signo => num
268 * Returns a signal number.
271 static VALUE
272 esignal_signo(VALUE self)
274 return rb_iv_get(self, "signo");
277 static VALUE
278 interrupt_init(int argc, VALUE *argv, VALUE self)
280 VALUE args[2];
282 args[0] = INT2FIX(SIGINT);
283 rb_scan_args(argc, argv, "01", &args[1]);
284 return rb_call_super(2, args);
287 void
288 ruby_default_signal(int sig)
290 #ifndef MACOS_UNUSE_SIGNAL
291 signal(sig, SIG_DFL);
292 raise(sig);
293 #endif
297 * call-seq:
298 * Process.kill(signal, pid, ...) => fixnum
300 * Sends the given signal to the specified process id(s), or to the
301 * current process if _pid_ is zero. _signal_ may be an
302 * integer signal number or a POSIX signal name (either with or without
303 * a +SIG+ prefix). If _signal_ is negative (or starts
304 * with a minus sign), kills process groups instead of
305 * processes. Not all signals are available on all platforms.
307 * pid = fork do
308 * Signal.trap("HUP") { puts "Ouch!"; exit }
309 * # ... do some work ...
310 * end
311 * # ...
312 * Process.kill("HUP", pid)
313 * Process.wait
315 * <em>produces:</em>
317 * Ouch!
320 VALUE
321 rb_f_kill(int argc, VALUE *argv)
323 #ifndef HAS_KILLPG
324 #define killpg(pg, sig) kill(-(pg), sig)
325 #endif
326 int negative = 0;
327 int sig;
328 int i;
329 const char *s;
331 rb_secure(2);
332 if (argc < 2)
333 rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)");
334 switch (TYPE(argv[0])) {
335 case T_FIXNUM:
336 sig = FIX2INT(argv[0]);
337 break;
339 case T_SYMBOL:
340 s = rb_id2name(SYM2ID(argv[0]));
341 if (!s) rb_raise(rb_eArgError, "bad signal");
342 goto str_signal;
344 case T_STRING:
345 s = RSTRING_PTR(argv[0]);
346 if (s[0] == '-') {
347 negative++;
348 s++;
350 str_signal:
351 if (strncmp("SIG", s, 3) == 0)
352 s += 3;
353 if((sig = signm2signo(s)) == 0)
354 rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
356 if (negative)
357 sig = -sig;
358 break;
360 default:
362 VALUE str;
364 str = rb_check_string_type(argv[0]);
365 if (!NIL_P(str)) {
366 s = RSTRING_PTR(str);
367 goto str_signal;
369 rb_raise(rb_eArgError, "bad signal type %s",
370 rb_obj_classname(argv[0]));
372 break;
375 if (sig < 0) {
376 sig = -sig;
377 for (i=1; i<argc; i++) {
378 if (killpg(NUM2PIDT(argv[i]), sig) < 0)
379 rb_sys_fail(0);
382 else {
383 for (i=1; i<argc; i++) {
384 if (kill(NUM2PIDT(argv[i]), sig) < 0)
385 rb_sys_fail(0);
388 rb_thread_polling();
389 return INT2FIX(i-1);
392 static struct {
393 VALUE cmd;
394 int safe;
395 } trap_list[NSIG];
396 static rb_atomic_t trap_pending_list[NSIG];
397 #if 0
398 static char rb_trap_accept_nativethreads[NSIG];
399 #endif
400 rb_atomic_t rb_trap_pending;
401 rb_atomic_t rb_trap_immediate;
402 int rb_prohibit_interrupt = 1;
404 VALUE
405 rb_get_trap_cmd(int sig)
407 return trap_list[sig].cmd;
410 void
411 rb_gc_mark_trap_list(void)
413 #ifndef MACOS_UNUSE_SIGNAL
414 int i;
416 for (i=0; i<NSIG; i++) {
417 if (trap_list[i].cmd)
418 rb_gc_mark(trap_list[i].cmd);
420 #endif /* MACOS_UNUSE_SIGNAL */
423 #ifdef __dietlibc__
424 #define sighandler_t sh_t
425 #endif
427 typedef RETSIGTYPE (*sighandler_t)(int);
429 #ifdef POSIX_SIGNAL
430 static sighandler_t
431 ruby_signal(int signum, sighandler_t handler)
433 struct sigaction sigact, old;
435 #if 0
436 rb_trap_accept_nativethreads[signum] = 0;
437 #endif
439 sigemptyset(&sigact.sa_mask);
440 #ifdef SA_SIGINFO
441 sigact.sa_sigaction = (void (*)(int, siginfo_t*, void*))handler;
442 sigact.sa_flags = SA_SIGINFO;
443 #else
444 sigact.sa_handler = handler;
445 sigact.sa_flags = 0;
446 #endif
448 #ifdef SA_NOCLDWAIT
449 if (signum == SIGCHLD && handler == SIG_IGN)
450 sigact.sa_flags |= SA_NOCLDWAIT;
451 #endif
452 sigaction(signum, &sigact, &old);
453 return old.sa_handler;
456 sighandler_t
457 posix_signal(int signum, sighandler_t handler)
459 return ruby_signal(signum, handler);
462 #else /* !POSIX_SIGNAL */
463 #define ruby_signal(sig,handler) (/* rb_trap_accept_nativethreads[sig] = 0,*/ signal((sig),(handler)))
464 #if 0 /* def HAVE_NATIVETHREAD */
465 static sighandler_t
466 ruby_nativethread_signal(int signum, sighandler_t handler)
468 sighandler_t old;
470 old = signal(signum, handler);
471 rb_trap_accept_nativethreads[signum] = 1;
472 return old;
474 #endif
475 #endif
477 static RETSIGTYPE
478 sighandler(int sig)
480 rb_vm_t *vm = GET_VM(); /* fix me for Multi-VM */
481 ATOMIC_INC(vm->signal_buff[sig]);
482 ATOMIC_INC(vm->buffered_signal_size);
484 #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
485 ruby_signal(sig, sighandler);
486 #endif
489 #if USE_TRAP_MASK
490 # ifdef HAVE_SIGPROCMASK
491 static sigset_t trap_last_mask;
492 # else
493 static int trap_last_mask;
494 # endif
495 #endif
497 #if HAVE_PTHREAD_H
498 #include <pthread.h>
499 #endif
501 void
502 rb_disable_interrupt(void)
504 #ifndef _WIN32
505 sigset_t mask;
506 sigfillset(&mask);
507 sigdelset(&mask, SIGVTALRM);
508 sigdelset(&mask, SIGSEGV);
509 pthread_sigmask(SIG_SETMASK, &mask, NULL);
510 #endif
513 void
514 rb_enable_interrupt(void)
516 #ifndef _WIN32
517 sigset_t mask;
518 sigemptyset(&mask);
519 pthread_sigmask(SIG_SETMASK, &mask, NULL);
520 #endif
524 rb_get_next_signal(rb_vm_t *vm)
526 int i, sig = 0;
528 for (i=1; i<RUBY_NSIG; i++) {
529 if (vm->signal_buff[i] > 0) {
530 rb_disable_interrupt();
532 ATOMIC_DEC(vm->signal_buff[i]);
533 ATOMIC_DEC(vm->buffered_signal_size);
535 rb_enable_interrupt();
536 sig = i;
537 break;
540 return sig;
543 #ifdef SIGBUS
544 static RETSIGTYPE
545 sigbus(int sig)
547 rb_bug("Bus Error");
549 #endif
551 #ifdef SIGSEGV
552 static int segv_received = 0;
553 static RETSIGTYPE
554 sigsegv(int sig)
556 if (segv_received) {
557 fprintf(stderr, "SEGV recieved in SEGV handler\n");
558 exit(EXIT_FAILURE);
560 else {
561 extern int ruby_disable_gc_stress;
562 segv_received = 1;
563 ruby_disable_gc_stress = 1;
564 rb_bug("Segmentation fault");
567 #endif
569 #ifdef SIGPIPE
570 static RETSIGTYPE
571 sigpipe(int sig)
573 /* do nothing */
575 #endif
577 static void
578 signal_exec(VALUE cmd, int sig)
580 rb_proc_t *proc;
581 VALUE signum = INT2FIX(sig);
583 if (TYPE(cmd) == T_STRING) {
584 rb_eval_cmd(cmd, rb_ary_new3(1, signum), trap_list[sig].safe);
585 return;
587 GetProcPtr(cmd, proc);
588 vm_invoke_proc(GET_THREAD(), proc, proc->block.self, 1, &signum, 0);
591 void
592 rb_trap_exit(void)
594 #ifndef MACOS_UNUSE_SIGNAL
595 if (trap_list[0].cmd) {
596 VALUE trap_exit = trap_list[0].cmd;
598 trap_list[0].cmd = 0;
599 signal_exec(trap_exit, 0);
601 #endif
604 void
605 rb_signal_exec(rb_thread_t *th, int sig)
607 VALUE cmd = rb_get_trap_cmd(sig);
609 if (cmd == 0) {
610 switch (sig) {
611 case SIGINT:
612 rb_interrupt();
613 break;
614 #ifdef SIGHUP
615 case SIGHUP:
616 #endif
617 #ifdef SIGQUIT
618 case SIGQUIT:
619 #endif
620 #ifdef SIGTERM
621 case SIGTERM:
622 #endif
623 #ifdef SIGALRM
624 case SIGALRM:
625 #endif
626 #ifdef SIGUSR1
627 case SIGUSR1:
628 #endif
629 #ifdef SIGUSR2
630 case SIGUSR2:
631 #endif
632 rb_thread_signal_raise(th, sig);
633 break;
636 else if (cmd == Qundef) {
637 rb_thread_signal_exit(th);
639 else {
640 signal_exec(cmd, sig);
644 void
645 rb_trap_exec(void)
647 #ifndef MACOS_UNUSE_SIGNAL
648 int i;
650 for (i=0; i<NSIG; i++) {
651 if (trap_pending_list[i]) {
652 trap_pending_list[i] = 0;
653 rb_signal_exec(GET_THREAD(), i);
656 #endif /* MACOS_UNUSE_SIGNAL */
657 rb_trap_pending = 0;
660 struct trap_arg {
661 #if USE_TRAP_MASK
662 # ifdef HAVE_SIGPROCMASK
663 sigset_t mask;
664 # else
665 int mask;
666 # endif
667 #endif
668 int sig;
669 sighandler_t func;
670 VALUE cmd;
673 static sighandler_t
674 default_handler(int sig)
676 sighandler_t func;
677 switch (sig) {
678 case SIGINT:
679 #ifdef SIGHUP
680 case SIGHUP:
681 #endif
682 #ifdef SIGQUIT
683 case SIGQUIT:
684 #endif
685 #ifdef SIGTERM
686 case SIGTERM:
687 #endif
688 #ifdef SIGALRM
689 case SIGALRM:
690 #endif
691 #ifdef SIGUSR1
692 case SIGUSR1:
693 #endif
694 #ifdef SIGUSR2
695 case SIGUSR2:
696 #endif
697 func = sighandler;
698 break;
699 #ifdef SIGBUS
700 case SIGBUS:
701 func = sigbus;
702 break;
703 #endif
704 #ifdef SIGSEGV
705 case SIGSEGV:
706 func = sigsegv;
707 break;
708 #endif
709 #ifdef SIGPIPE
710 case SIGPIPE:
711 func = sigpipe;
712 break;
713 #endif
714 default:
715 func = SIG_DFL;
716 break;
719 return func;
722 static sighandler_t
723 trap_handler(VALUE *cmd, int sig)
725 sighandler_t func = sighandler;
726 VALUE command;
728 if (NIL_P(*cmd)) {
729 func = SIG_IGN;
731 else {
732 command = rb_check_string_type(*cmd);
733 if (!NIL_P(command)) {
734 SafeStringValue(command); /* taint check */
735 *cmd = command;
736 switch (RSTRING_LEN(command)) {
737 case 0:
738 goto sig_ign;
739 break;
740 case 14:
741 if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) {
742 func = SIG_DFL;
743 *cmd = 0;
745 break;
746 case 7:
747 if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) {
748 sig_ign:
749 func = SIG_IGN;
750 *cmd = 0;
752 else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
753 sig_dfl:
754 func = default_handler(sig);
755 *cmd = 0;
757 else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) {
758 goto sig_dfl;
760 break;
761 case 6:
762 if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) {
763 goto sig_ign;
765 break;
766 case 4:
767 if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) {
768 *cmd = Qundef;
770 break;
773 else {
774 rb_proc_t *proc;
775 GetProcPtr(*cmd, proc);
779 return func;
782 static int
783 trap_signm(VALUE vsig)
785 int sig = -1;
786 const char *s;
788 switch (TYPE(vsig)) {
789 case T_FIXNUM:
790 sig = FIX2INT(vsig);
791 if (sig < 0 || sig >= NSIG) {
792 rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
794 break;
796 case T_SYMBOL:
797 s = rb_id2name(SYM2ID(vsig));
798 if (!s) rb_raise(rb_eArgError, "bad signal");
799 goto str_signal;
801 default:
802 s = StringValuePtr(vsig);
804 str_signal:
805 if (strncmp("SIG", s, 3) == 0)
806 s += 3;
807 sig = signm2signo(s);
808 if (sig == 0 && strcmp(s, "EXIT") != 0)
809 rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
811 return sig;
814 static VALUE
815 trap(struct trap_arg *arg)
817 sighandler_t oldfunc, func = arg->func;
818 VALUE oldcmd, command = arg->cmd;
819 int sig = arg->sig;
821 oldfunc = ruby_signal(sig, func);
822 oldcmd = trap_list[sig].cmd;
823 switch (oldcmd) {
824 case 0:
825 if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
826 else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
827 else oldcmd = Qnil;
828 break;
829 case Qundef:
830 oldcmd = rb_str_new2("EXIT");
831 break;
834 trap_list[sig].cmd = command;
835 trap_list[sig].safe = rb_safe_level();
836 /* enable at least specified signal. */
837 #if USE_TRAP_MASK
838 #ifdef HAVE_SIGPROCMASK
839 sigdelset(&arg->mask, sig);
840 #else
841 arg->mask &= ~sigmask(sig);
842 #endif
843 #endif
844 return oldcmd;
847 #if USE_TRAP_MASK
848 static VALUE
849 trap_ensure(struct trap_arg *arg)
851 /* enable interrupt */
852 #ifdef HAVE_SIGPROCMASK
853 sigprocmask(SIG_SETMASK, &arg->mask, NULL);
854 #else
855 sigsetmask(arg->mask);
856 #endif
857 trap_last_mask = arg->mask;
858 return 0;
860 #endif
862 void
863 rb_trap_restore_mask(void)
865 #if USE_TRAP_MASK
866 # ifdef HAVE_SIGPROCMASK
867 sigprocmask(SIG_SETMASK, &trap_last_mask, NULL);
868 # else
869 sigsetmask(trap_last_mask);
870 # endif
871 #endif
875 * call-seq:
876 * Signal.trap( signal, command ) => obj
877 * Signal.trap( signal ) {| | block } => obj
879 * Specifies the handling of signals. The first parameter is a signal
880 * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
881 * signal number. The characters ``SIG'' may be omitted from the
882 * signal name. The command or block specifies code to be run when the
883 * signal is raised.
884 * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
885 * will be ignored.
886 * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
887 * will be invoked.
888 * If the command is ``EXIT'', the script will be terminated by the signal.
889 * If the command is ``SYSTEM_DEFAULT'', the operating system's default
890 * handler will be invoked.
891 * Otherwise, the given command or block will be run.
892 * The special signal name ``EXIT'' or signal number zero will be
893 * invoked just prior to program termination.
894 * trap returns the previous handler for the given signal.
896 * Signal.trap(0, proc { puts "Terminating: #{$$}" })
897 * Signal.trap("CLD") { puts "Child died" }
898 * fork && Process.wait
900 * produces:
901 * Terminating: 27461
902 * Child died
903 * Terminating: 27460
905 static VALUE
906 sig_trap(int argc, VALUE *argv)
908 struct trap_arg arg;
910 rb_secure(2);
911 if (argc == 0 || argc > 2) {
912 rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
915 arg.sig = trap_signm(argv[0]);
916 if (argc == 1) {
917 arg.cmd = rb_block_proc();
918 arg.func = sighandler;
920 else if (argc == 2) {
921 arg.cmd = argv[1];
922 arg.func = trap_handler(&arg.cmd, arg.sig);
925 if (OBJ_TAINTED(arg.cmd)) {
926 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
928 #if USE_TRAP_MASK
929 /* disable interrupt */
930 # ifdef HAVE_SIGPROCMASK
931 sigfillset(&arg.mask);
932 sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask);
933 # else
934 arg.mask = sigblock(~0);
935 # endif
937 return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
938 #else
939 return trap(&arg);
940 #endif
944 * call-seq:
945 * Signal.list => a_hash
947 * Returns a list of signal names mapped to the corresponding
948 * underlying signal numbers.
950 * 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}
952 static VALUE
953 sig_list(void)
955 VALUE h = rb_hash_new();
956 const struct signals *sigs;
958 for (sigs = siglist; sigs->signm; sigs++) {
959 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
961 return h;
964 static void
965 install_sighandler(int signum, sighandler_t handler)
967 sighandler_t old;
969 old = ruby_signal(signum, handler);
970 if (old != SIG_DFL) {
971 ruby_signal(signum, old);
975 #if defined(SIGCLD) || defined(SIGCHLD)
976 static void
977 init_sigchld(int sig)
979 sighandler_t oldfunc;
980 #if USE_TRAP_MASK
981 # ifdef HAVE_SIGPROCMASK
982 sigset_t mask;
983 # else
984 int mask;
985 # endif
986 #endif
988 #if USE_TRAP_MASK
989 /* disable interrupt */
990 # ifdef HAVE_SIGPROCMASK
991 sigfillset(&mask);
992 sigprocmask(SIG_BLOCK, &mask, &mask);
993 # else
994 mask = sigblock(~0);
995 # endif
996 #endif
998 oldfunc = ruby_signal(sig, SIG_DFL);
999 if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
1000 ruby_signal(sig, oldfunc);
1001 } else {
1002 trap_list[sig].cmd = 0;
1005 #if USE_TRAP_MASK
1006 #ifdef HAVE_SIGPROCMASK
1007 sigdelset(&mask, sig);
1008 sigprocmask(SIG_SETMASK, &mask, NULL);
1009 #else
1010 mask &= ~sigmask(sig);
1011 sigsetmask(mask);
1012 #endif
1013 trap_last_mask = mask;
1014 #endif
1016 #endif
1018 void
1019 ruby_sig_finalize()
1021 sighandler_t oldfunc;
1023 oldfunc = ruby_signal(SIGINT, SIG_IGN);
1024 if (oldfunc == sighandler) {
1025 ruby_signal(SIGINT, SIG_DFL);
1030 #ifdef RUBY_DEBUG_ENV
1031 int ruby_enable_coredump = 0;
1032 #endif
1035 * Many operating systems allow signals to be sent to running
1036 * processes. Some signals have a defined effect on the process, while
1037 * others may be trapped at the code level and acted upon. For
1038 * example, your process may trap the USR1 signal and use it to toggle
1039 * debugging, and may use TERM to initiate a controlled shutdown.
1041 * pid = fork do
1042 * Signal.trap("USR1") do
1043 * $debug = !$debug
1044 * puts "Debug now: #$debug"
1045 * end
1046 * Signal.trap("TERM") do
1047 * puts "Terminating..."
1048 * shutdown()
1049 * end
1050 * # . . . do some work . . .
1051 * end
1053 * Process.detach(pid)
1055 * # Controlling program:
1056 * Process.kill("USR1", pid)
1057 * # ...
1058 * Process.kill("USR1", pid)
1059 * # ...
1060 * Process.kill("TERM", pid)
1062 * produces:
1063 * Debug now: true
1064 * Debug now: false
1065 * Terminating...
1067 * The list of available signal names and their interpretation is
1068 * system dependent. Signal delivery semantics may also vary between
1069 * systems; in particular signal delivery may not always be reliable.
1071 void
1072 Init_signal(void)
1074 #ifndef MACOS_UNUSE_SIGNAL
1075 VALUE mSignal = rb_define_module("Signal");
1077 rb_define_global_function("trap", sig_trap, -1);
1078 rb_define_module_function(mSignal, "trap", sig_trap, -1);
1079 rb_define_module_function(mSignal, "list", sig_list, 0);
1081 rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
1082 rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
1083 rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
1084 rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
1086 install_sighandler(SIGINT, sighandler);
1087 #ifdef SIGHUP
1088 install_sighandler(SIGHUP, sighandler);
1089 #endif
1090 #ifdef SIGQUIT
1091 install_sighandler(SIGQUIT, sighandler);
1092 #endif
1093 #ifdef SIGTERM
1094 install_sighandler(SIGTERM, sighandler);
1095 #endif
1096 #ifdef SIGALRM
1097 install_sighandler(SIGALRM, sighandler);
1098 #endif
1099 #ifdef SIGUSR1
1100 install_sighandler(SIGUSR1, sighandler);
1101 #endif
1102 #ifdef SIGUSR2
1103 install_sighandler(SIGUSR2, sighandler);
1104 #endif
1106 #ifdef RUBY_DEBUG_ENV
1107 if (!ruby_enable_coredump)
1108 #endif
1110 #ifdef SIGBUS
1111 install_sighandler(SIGBUS, sigbus);
1112 #endif
1113 #ifdef SIGSEGV
1114 install_sighandler(SIGSEGV, sigsegv);
1115 #endif
1117 #ifdef SIGPIPE
1118 install_sighandler(SIGPIPE, sigpipe);
1119 #endif
1121 #if defined(SIGCLD)
1122 init_sigchld(SIGCLD);
1123 #elif defined(SIGCHLD)
1124 init_sigchld(SIGCHLD);
1125 #endif
1127 #endif /* MACOS_UNUSE_SIGNAL */