* re.c (unescape_nonascii): make regexp fixed_encoding if \p is used.
[ruby-svn.git] / signal.c
blobe35f3713ed5450f2b28787853240b67ecc991f64
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 } trap_list[NSIG];
395 static rb_atomic_t trap_pending_list[NSIG];
396 #if 0
397 static char rb_trap_accept_nativethreads[NSIG];
398 #endif
399 rb_atomic_t rb_trap_pending;
400 rb_atomic_t rb_trap_immediate;
401 int rb_prohibit_interrupt = 1;
403 VALUE
404 rb_get_trap_cmd(int sig)
406 return trap_list[sig].cmd;
409 void
410 rb_gc_mark_trap_list(void)
412 #ifndef MACOS_UNUSE_SIGNAL
413 int i;
415 for (i=0; i<NSIG; i++) {
416 if (trap_list[i].cmd)
417 rb_gc_mark(trap_list[i].cmd);
419 #endif /* MACOS_UNUSE_SIGNAL */
422 #ifdef __dietlibc__
423 #define sighandler_t sh_t
424 #endif
426 typedef RETSIGTYPE (*sighandler_t)(int);
428 #ifdef POSIX_SIGNAL
429 static sighandler_t
430 ruby_signal(int signum, sighandler_t handler)
432 struct sigaction sigact, old;
434 #if 0
435 rb_trap_accept_nativethreads[signum] = 0;
436 #endif
438 sigemptyset(&sigact.sa_mask);
439 #ifdef SA_SIGINFO
440 sigact.sa_sigaction = (void (*)(int, siginfo_t*, void*))handler;
441 sigact.sa_flags = SA_SIGINFO;
442 #else
443 sigact.sa_handler = handler;
444 sigact.sa_flags = 0;
445 #endif
447 #ifdef SA_NOCLDWAIT
448 if (signum == SIGCHLD && handler == SIG_IGN)
449 sigact.sa_flags |= SA_NOCLDWAIT;
450 #endif
451 sigaction(signum, &sigact, &old);
452 return old.sa_handler;
455 sighandler_t
456 posix_signal(int signum, sighandler_t handler)
458 return ruby_signal(signum, handler);
461 #else /* !POSIX_SIGNAL */
462 #define ruby_signal(sig,handler) (/* rb_trap_accept_nativethreads[sig] = 0,*/ signal((sig),(handler)))
463 #if 0 /* def HAVE_NATIVETHREAD */
464 static sighandler_t
465 ruby_nativethread_signal(int signum, sighandler_t handler)
467 sighandler_t old;
469 old = signal(signum, handler);
470 rb_trap_accept_nativethreads[signum] = 1;
471 return old;
473 #endif
474 #endif
476 static RETSIGTYPE
477 sighandler(int sig)
479 rb_vm_t *vm = GET_VM(); /* fix me for Multi-VM */
480 ATOMIC_INC(vm->signal_buff[sig]);
481 ATOMIC_INC(vm->buffered_signal_size);
483 #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
484 ruby_signal(sig, sighandler);
485 #endif
488 #if USE_TRAP_MASK
489 # ifdef HAVE_SIGPROCMASK
490 static sigset_t trap_last_mask;
491 # else
492 static int trap_last_mask;
493 # endif
494 #endif
496 #if HAVE_PTHREAD_H
497 #include <pthread.h>
498 #endif
500 void
501 rb_disable_interrupt(void)
503 #ifndef _WIN32
504 sigset_t mask;
505 sigfillset(&mask);
506 sigdelset(&mask, SIGVTALRM);
507 sigdelset(&mask, SIGSEGV);
508 pthread_sigmask(SIG_SETMASK, &mask, NULL);
509 #endif
512 void
513 rb_enable_interrupt(void)
515 #ifndef _WIN32
516 sigset_t mask;
517 sigemptyset(&mask);
518 pthread_sigmask(SIG_SETMASK, &mask, NULL);
519 #endif
523 rb_get_next_signal(rb_vm_t *vm)
525 int i, sig = 0;
527 for (i=1; i<RUBY_NSIG; i++) {
528 if (vm->signal_buff[i] > 0) {
529 rb_disable_interrupt();
531 ATOMIC_DEC(vm->signal_buff[i]);
532 ATOMIC_DEC(vm->buffered_signal_size);
534 rb_enable_interrupt();
535 sig = i;
536 break;
539 return sig;
542 #ifdef SIGBUS
543 static RETSIGTYPE
544 sigbus(int sig)
546 rb_bug("Bus Error");
548 #endif
550 #ifdef SIGSEGV
551 static int segv_received = 0;
552 static RETSIGTYPE
553 sigsegv(int sig)
555 if (segv_received) {
556 fprintf(stderr, "SEGV recieved in SEGV handler\n");
557 exit(EXIT_FAILURE);
559 else {
560 extern int ruby_disable_gc_stress;
561 segv_received = 1;
562 ruby_disable_gc_stress = 1;
563 rb_bug("Segmentation fault");
566 #endif
568 #ifdef SIGPIPE
569 static RETSIGTYPE
570 sigpipe(int sig)
572 /* do nothing */
574 #endif
576 static void
577 signal_exec(VALUE cmd, int sig)
579 rb_proc_t *proc;
580 VALUE signum = INT2FIX(sig);
581 GetProcPtr(cmd, proc);
582 vm_invoke_proc(GET_THREAD(), proc, proc->block.self, 1, &signum, 0);
585 void
586 rb_trap_exit(void)
588 #ifndef MACOS_UNUSE_SIGNAL
589 if (trap_list[0].cmd) {
590 VALUE trap_exit = trap_list[0].cmd;
592 trap_list[0].cmd = 0;
593 signal_exec(trap_exit, 0);
595 #endif
598 void
599 rb_signal_exec(rb_thread_t *th, int sig)
601 VALUE cmd = rb_get_trap_cmd(sig);
603 if (cmd == 0) {
604 switch (sig) {
605 case SIGINT:
606 rb_interrupt();
607 break;
608 #ifdef SIGHUP
609 case SIGHUP:
610 #endif
611 #ifdef SIGQUIT
612 case SIGQUIT:
613 #endif
614 #ifdef SIGTERM
615 case SIGTERM:
616 #endif
617 #ifdef SIGALRM
618 case SIGALRM:
619 #endif
620 #ifdef SIGUSR1
621 case SIGUSR1:
622 #endif
623 #ifdef SIGUSR2
624 case SIGUSR2:
625 #endif
626 rb_thread_signal_raise(th, sig);
627 break;
630 else if (cmd == Qundef) {
631 rb_thread_signal_exit(th);
633 else {
634 signal_exec(cmd, sig);
638 void
639 rb_trap_exec(void)
641 #ifndef MACOS_UNUSE_SIGNAL
642 int i;
644 for (i=0; i<NSIG; i++) {
645 if (trap_pending_list[i]) {
646 trap_pending_list[i] = 0;
647 rb_signal_exec(GET_THREAD(), i);
650 #endif /* MACOS_UNUSE_SIGNAL */
651 rb_trap_pending = 0;
654 struct trap_arg {
655 #if USE_TRAP_MASK
656 # ifdef HAVE_SIGPROCMASK
657 sigset_t mask;
658 # else
659 int mask;
660 # endif
661 #endif
662 int sig;
663 sighandler_t func;
664 VALUE cmd;
667 static sighandler_t
668 default_handler(int sig)
670 sighandler_t func;
671 switch (sig) {
672 case SIGINT:
673 #ifdef SIGHUP
674 case SIGHUP:
675 #endif
676 #ifdef SIGQUIT
677 case SIGQUIT:
678 #endif
679 #ifdef SIGTERM
680 case SIGTERM:
681 #endif
682 #ifdef SIGALRM
683 case SIGALRM:
684 #endif
685 #ifdef SIGUSR1
686 case SIGUSR1:
687 #endif
688 #ifdef SIGUSR2
689 case SIGUSR2:
690 #endif
691 func = sighandler;
692 break;
693 #ifdef SIGBUS
694 case SIGBUS:
695 func = sigbus;
696 break;
697 #endif
698 #ifdef SIGSEGV
699 case SIGSEGV:
700 func = sigsegv;
701 break;
702 #endif
703 #ifdef SIGPIPE
704 case SIGPIPE:
705 func = sigpipe;
706 break;
707 #endif
708 default:
709 func = SIG_DFL;
710 break;
713 return func;
716 static RETSIGTYPE
717 wrong_trap(int sig)
721 static sighandler_t
722 trap_handler(VALUE *cmd, int sig)
724 sighandler_t func = wrong_trap;
725 VALUE command;
727 if (NIL_P(*cmd)) {
728 func = SIG_IGN;
730 else {
731 command = rb_check_string_type(*cmd);
732 if (!NIL_P(command)) {
733 SafeStringValue(command); /* taint check */
734 switch (RSTRING_LEN(command)) {
735 case 0:
736 goto sig_ign;
737 break;
738 case 14:
739 if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) {
740 func = SIG_DFL;
741 *cmd = 0;
743 break;
744 case 7:
745 if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) {
746 sig_ign:
747 func = SIG_IGN;
748 *cmd = 0;
750 else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
751 sig_dfl:
752 func = default_handler(sig);
753 *cmd = 0;
755 else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) {
756 goto sig_dfl;
758 break;
759 case 6:
760 if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) {
761 goto sig_ign;
763 break;
764 case 4:
765 if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) {
766 func = sighandler;
767 *cmd = Qundef;
769 break;
771 if (func == wrong_trap) {
772 rb_raise(rb_eArgError, "wrong trap - %s", RSTRING_PTR(command));
775 else {
776 rb_proc_t *proc;
777 GetProcPtr(*cmd, proc);
778 func = sighandler;
782 return func;
785 static int
786 trap_signm(VALUE vsig)
788 int sig = -1;
789 const char *s;
791 switch (TYPE(vsig)) {
792 case T_FIXNUM:
793 sig = FIX2INT(vsig);
794 if (sig < 0 || sig >= NSIG) {
795 rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
797 break;
799 case T_SYMBOL:
800 s = rb_id2name(SYM2ID(vsig));
801 if (!s) rb_raise(rb_eArgError, "bad signal");
802 goto str_signal;
804 default:
805 s = StringValuePtr(vsig);
807 str_signal:
808 if (strncmp("SIG", s, 3) == 0)
809 s += 3;
810 sig = signm2signo(s);
811 if (sig == 0 && strcmp(s, "EXIT") != 0)
812 rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
814 return sig;
817 static VALUE
818 trap(struct trap_arg *arg)
820 sighandler_t oldfunc, func = arg->func;
821 VALUE oldcmd, command = arg->cmd;
822 int sig = arg->sig;
824 oldfunc = ruby_signal(sig, func);
825 oldcmd = trap_list[sig].cmd;
826 switch (oldcmd) {
827 case 0:
828 if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
829 else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
830 else oldcmd = Qnil;
831 break;
832 case Qundef:
833 oldcmd = rb_str_new2("EXIT");
834 break;
837 trap_list[sig].cmd = command;
838 /* enable at least specified signal. */
839 #if USE_TRAP_MASK
840 #ifdef HAVE_SIGPROCMASK
841 sigdelset(&arg->mask, sig);
842 #else
843 arg->mask &= ~sigmask(sig);
844 #endif
845 #endif
846 return oldcmd;
849 #if USE_TRAP_MASK
850 static VALUE
851 trap_ensure(struct trap_arg *arg)
853 /* enable interrupt */
854 #ifdef HAVE_SIGPROCMASK
855 sigprocmask(SIG_SETMASK, &arg->mask, NULL);
856 #else
857 sigsetmask(arg->mask);
858 #endif
859 trap_last_mask = arg->mask;
860 return 0;
862 #endif
864 void
865 rb_trap_restore_mask(void)
867 #if USE_TRAP_MASK
868 # ifdef HAVE_SIGPROCMASK
869 sigprocmask(SIG_SETMASK, &trap_last_mask, NULL);
870 # else
871 sigsetmask(trap_last_mask);
872 # endif
873 #endif
877 * call-seq:
878 * Signal.trap( signal, command ) => obj
879 * Signal.trap( signal ) {| | block } => obj
881 * Specifies the handling of signals. The first parameter is a signal
882 * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
883 * signal number. The characters ``SIG'' may be omitted from the
884 * signal name. The command or block specifies code to be run when the
885 * signal is raised.
886 * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
887 * will be ignored.
888 * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
889 * will be invoked.
890 * If the command is ``EXIT'', the script will be terminated by the signal.
891 * If the command is ``SYSTEM_DEFAULT'', the operating system's default
892 * handler will be invoked.
893 * Otherwise, the given command or block will be run.
894 * The special signal name ``EXIT'' or signal number zero will be
895 * invoked just prior to program termination.
896 * trap returns the previous handler for the given signal.
898 * Signal.trap(0, proc { puts "Terminating: #{$$}" })
899 * Signal.trap("CLD") { puts "Child died" }
900 * fork && Process.wait
902 * produces:
903 * Terminating: 27461
904 * Child died
905 * Terminating: 27460
907 static VALUE
908 sig_trap(int argc, VALUE *argv)
910 struct trap_arg arg;
912 rb_secure(2);
913 if (argc == 0 || argc > 2) {
914 rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
917 arg.sig = trap_signm(argv[0]);
918 if (argc == 1) {
919 arg.cmd = rb_block_proc();
920 arg.func = sighandler;
922 else if (argc == 2) {
923 arg.cmd = argv[1];
924 arg.func = trap_handler(&arg.cmd, arg.sig);
927 if (OBJ_TAINTED(arg.cmd)) {
928 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
930 #if USE_TRAP_MASK
931 /* disable interrupt */
932 # ifdef HAVE_SIGPROCMASK
933 sigfillset(&arg.mask);
934 sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask);
935 # else
936 arg.mask = sigblock(~0);
937 # endif
939 return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
940 #else
941 return trap(&arg);
942 #endif
946 * call-seq:
947 * Signal.list => a_hash
949 * Returns a list of signal names mapped to the corresponding
950 * underlying signal numbers.
952 * 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}
954 static VALUE
955 sig_list(void)
957 VALUE h = rb_hash_new();
958 const struct signals *sigs;
960 for (sigs = siglist; sigs->signm; sigs++) {
961 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
963 return h;
966 static void
967 install_sighandler(int signum, sighandler_t handler)
969 sighandler_t old;
971 old = ruby_signal(signum, handler);
972 if (old != SIG_DFL) {
973 ruby_signal(signum, old);
977 #if defined(SIGCLD) || defined(SIGCHLD)
978 static void
979 init_sigchld(int sig)
981 sighandler_t oldfunc;
982 #if USE_TRAP_MASK
983 # ifdef HAVE_SIGPROCMASK
984 sigset_t mask;
985 # else
986 int mask;
987 # endif
988 #endif
990 #if USE_TRAP_MASK
991 /* disable interrupt */
992 # ifdef HAVE_SIGPROCMASK
993 sigfillset(&mask);
994 sigprocmask(SIG_BLOCK, &mask, &mask);
995 # else
996 mask = sigblock(~0);
997 # endif
998 #endif
1000 oldfunc = ruby_signal(sig, SIG_DFL);
1001 if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
1002 ruby_signal(sig, oldfunc);
1003 } else {
1004 trap_list[sig].cmd = 0;
1007 #if USE_TRAP_MASK
1008 #ifdef HAVE_SIGPROCMASK
1009 sigdelset(&mask, sig);
1010 sigprocmask(SIG_SETMASK, &mask, NULL);
1011 #else
1012 mask &= ~sigmask(sig);
1013 sigsetmask(mask);
1014 #endif
1015 trap_last_mask = mask;
1016 #endif
1018 #endif
1020 void
1021 ruby_sig_finalize()
1023 sighandler_t oldfunc;
1025 oldfunc = ruby_signal(SIGINT, SIG_IGN);
1026 if (oldfunc == sighandler) {
1027 ruby_signal(SIGINT, SIG_DFL);
1032 #ifdef RUBY_DEBUG_ENV
1033 int ruby_enable_coredump = 0;
1034 #endif
1037 * Many operating systems allow signals to be sent to running
1038 * processes. Some signals have a defined effect on the process, while
1039 * others may be trapped at the code level and acted upon. For
1040 * example, your process may trap the USR1 signal and use it to toggle
1041 * debugging, and may use TERM to initiate a controlled shutdown.
1043 * pid = fork do
1044 * Signal.trap("USR1") do
1045 * $debug = !$debug
1046 * puts "Debug now: #$debug"
1047 * end
1048 * Signal.trap("TERM") do
1049 * puts "Terminating..."
1050 * shutdown()
1051 * end
1052 * # . . . do some work . . .
1053 * end
1055 * Process.detach(pid)
1057 * # Controlling program:
1058 * Process.kill("USR1", pid)
1059 * # ...
1060 * Process.kill("USR1", pid)
1061 * # ...
1062 * Process.kill("TERM", pid)
1064 * produces:
1065 * Debug now: true
1066 * Debug now: false
1067 * Terminating...
1069 * The list of available signal names and their interpretation is
1070 * system dependent. Signal delivery semantics may also vary between
1071 * systems; in particular signal delivery may not always be reliable.
1073 void
1074 Init_signal(void)
1076 #ifndef MACOS_UNUSE_SIGNAL
1077 VALUE mSignal = rb_define_module("Signal");
1079 rb_define_global_function("trap", sig_trap, -1);
1080 rb_define_module_function(mSignal, "trap", sig_trap, -1);
1081 rb_define_module_function(mSignal, "list", sig_list, 0);
1083 rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
1084 rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
1085 rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
1086 rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
1088 install_sighandler(SIGINT, sighandler);
1089 #ifdef SIGHUP
1090 install_sighandler(SIGHUP, sighandler);
1091 #endif
1092 #ifdef SIGQUIT
1093 install_sighandler(SIGQUIT, sighandler);
1094 #endif
1095 #ifdef SIGTERM
1096 install_sighandler(SIGTERM, sighandler);
1097 #endif
1098 #ifdef SIGALRM
1099 install_sighandler(SIGALRM, sighandler);
1100 #endif
1101 #ifdef SIGUSR1
1102 install_sighandler(SIGUSR1, sighandler);
1103 #endif
1104 #ifdef SIGUSR2
1105 install_sighandler(SIGUSR2, sighandler);
1106 #endif
1108 #ifdef RUBY_DEBUG_ENV
1109 if (!ruby_enable_coredump)
1110 #endif
1112 #ifdef SIGBUS
1113 install_sighandler(SIGBUS, sigbus);
1114 #endif
1115 #ifdef SIGSEGV
1116 install_sighandler(SIGSEGV, sigsegv);
1117 #endif
1119 #ifdef SIGPIPE
1120 install_sighandler(SIGPIPE, sigpipe);
1121 #endif
1123 #if defined(SIGCLD)
1124 init_sigchld(SIGCLD);
1125 #elif defined(SIGCHLD)
1126 init_sigchld(SIGCHLD);
1127 #endif
1129 #endif /* MACOS_UNUSE_SIGNAL */