Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 1140 lines (1035 sloc) 22.57 kb
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1 /**********************************************************************
2
3 signal.c -
4
5 $Author: mame $
6 created at: Tue Dec 20 10:13:44 JST 1994
7
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
11
12 **********************************************************************/
13
14 #include "ruby/ruby.h"
15 #include "ruby/signal.h"
16 #include "ruby/node.h"
17 #include "id.h"
18 #include "roxor.h"
19 #include <signal.h>
20 #include <stdio.h>
21
22 #ifdef __BEOS__
23 #undef SIGBUS
24 #endif
25
26 #if defined HAVE_SIGPROCMASK || defined HAVE_SIGSETMASK
27 #define USE_TRAP_MASK 1
28 #else
29 #define USE_TRAP_MASK 0
30 #endif
31
32 #ifndef NSIG
33 # ifdef DJGPP
34 # define NSIG SIGMAX
35 # else
36 # define NSIG (_SIGMAX + 1) /* For QNX */
37 # endif
38 #endif
39
40 static const struct signals {
41 const char *signm;
42 int signo;
43 } siglist [] = {
44 {"EXIT", 0},
45 #ifdef SIGHUP
46 {"HUP", SIGHUP},
47 #endif
48 {"INT", SIGINT},
49 #ifdef SIGQUIT
50 {"QUIT", SIGQUIT},
51 #endif
52 #ifdef SIGILL
53 {"ILL", SIGILL},
54 #endif
55 #ifdef SIGTRAP
56 {"TRAP", SIGTRAP},
57 #endif
58 #ifdef SIGIOT
59 {"IOT", SIGIOT},
60 #endif
61 #ifdef SIGABRT
62 {"ABRT", SIGABRT},
63 #endif
64 #ifdef SIGEMT
65 {"EMT", SIGEMT},
66 #endif
67 #ifdef SIGFPE
68 {"FPE", SIGFPE},
69 #endif
70 #ifdef SIGKILL
71 {"KILL", SIGKILL},
72 #endif
73 #ifdef SIGBUS
74 {"BUS", SIGBUS},
75 #endif
76 #ifdef SIGSEGV
77 {"SEGV", SIGSEGV},
78 #endif
79 #ifdef SIGSYS
80 {"SYS", SIGSYS},
81 #endif
82 #ifdef SIGPIPE
83 {"PIPE", SIGPIPE},
84 #endif
85 #ifdef SIGALRM
86 {"ALRM", SIGALRM},
87 #endif
88 #ifdef SIGTERM
89 {"TERM", SIGTERM},
90 #endif
91 #ifdef SIGURG
92 {"URG", SIGURG},
93 #endif
94 #ifdef SIGSTOP
95 {"STOP", SIGSTOP},
96 #endif
97 #ifdef SIGTSTP
98 {"TSTP", SIGTSTP},
99 #endif
100 #ifdef SIGCONT
101 {"CONT", SIGCONT},
102 #endif
103 #ifdef SIGCHLD
104 {"CHLD", SIGCHLD},
105 #endif
106 #ifdef SIGCLD
107 {"CLD", SIGCLD},
108 #else
109 # ifdef SIGCHLD
110 {"CLD", SIGCHLD},
111 # endif
112 #endif
113 #ifdef SIGTTIN
114 {"TTIN", SIGTTIN},
115 #endif
116 #ifdef SIGTTOU
117 {"TTOU", SIGTTOU},
118 #endif
119 #ifdef SIGIO
120 {"IO", SIGIO},
121 #endif
122 #ifdef SIGXCPU
123 {"XCPU", SIGXCPU},
124 #endif
125 #ifdef SIGXFSZ
126 {"XFSZ", SIGXFSZ},
127 #endif
128 #ifdef SIGVTALRM
129 {"VTALRM", SIGVTALRM},
130 #endif
131 #ifdef SIGPROF
132 {"PROF", SIGPROF},
133 #endif
134 #ifdef SIGWINCH
135 {"WINCH", SIGWINCH},
136 #endif
137 #ifdef SIGUSR1
138 {"USR1", SIGUSR1},
139 #endif
140 #ifdef SIGUSR2
141 {"USR2", SIGUSR2},
142 #endif
143 #ifdef SIGLOST
144 {"LOST", SIGLOST},
145 #endif
146 #ifdef SIGMSG
147 {"MSG", SIGMSG},
148 #endif
149 #ifdef SIGPWR
150 {"PWR", SIGPWR},
151 #endif
152 #ifdef SIGPOLL
153 {"POLL", SIGPOLL},
154 #endif
155 #ifdef SIGDANGER
156 {"DANGER", SIGDANGER},
157 #endif
158 #ifdef SIGMIGRATE
159 {"MIGRATE", SIGMIGRATE},
160 #endif
161 #ifdef SIGPRE
162 {"PRE", SIGPRE},
163 #endif
164 #ifdef SIGGRANT
165 {"GRANT", SIGGRANT},
166 #endif
167 #ifdef SIGRETRACT
168 {"RETRACT", SIGRETRACT},
169 #endif
170 #ifdef SIGSOUND
171 {"SOUND", SIGSOUND},
172 #endif
173 #ifdef SIGINFO
174 {"INFO", SIGINFO},
175 #endif
176 {NULL, 0}
177 };
178
179 static int
180 signm2signo(const char *nm)
181 {
182 const struct signals *sigs;
183
184 for (sigs = siglist; sigs->signm; sigs++)
185 if (strcmp(sigs->signm, nm) == 0)
186 return sigs->signo;
187 return 0;
188 }
189
190 static const char*
191 signo2signm(int no)
192 {
193 const struct signals *sigs;
194
195 for (sigs = siglist; sigs->signm; sigs++)
196 if (sigs->signo == no)
197 return sigs->signm;
198 return 0;
199 }
200
201 const char *
202 ruby_signal_name(int no)
203 {
204 return signo2signm(no);
205 }
206
207 /*
208 * call-seq:
209 * SignalException.new(sig) => signal_exception
210 *
211 * Construct a new SignalException object. +sig+ should be a known
212 * signal name, or a signal number.
213 */
214
215 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
216 esignal_init(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
217 {
218 int argnum = 1;
219 VALUE sig = Qnil;
220 int signo;
221 const char *signm;
222
223 if (argc > 0) {
224 sig = rb_check_to_integer(argv[0], "to_int");
225 if (!NIL_P(sig)) argnum = 2;
226 else sig = argv[0];
227 }
228 if (argc < 1 || argnum < argc) {
229 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
230 argc, argnum);
231 }
232 if (argnum == 2) {
233 signo = NUM2INT(sig);
234 if (signo < 0 || signo > NSIG) {
235 rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
236 }
237 if (argc > 1) {
238 sig = argv[1];
239 }
240 else {
241 signm = signo2signm(signo);
242 if (signm) {
243 sig = rb_sprintf("SIG%s", signm);
244 }
245 else {
246 sig = rb_sprintf("SIG%u", signo);
247 }
248 }
249 }
250 else {
251 signm = SYMBOL_P(sig) ? rb_sym2name(sig) : StringValuePtr(sig);
252 if (strncmp(signm, "SIG", 3) == 0) signm += 3;
253 signo = signm2signo(signm);
254 if (!signo) {
255 rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
256 }
257 sig = rb_sprintf("SIG%s", signm);
258 }
259 //rb_call_super(1, &sig);
260 rb_vm_call(self, selInitialize2, 1, &sig, true);
261 rb_iv_set(self, "signo", INT2NUM(signo));
262
263 return self;
264 }
265
266 /*
267 * call-seq:
268 * signal_exception.signo => num
269 *
270 * Returns a signal number.
271 */
272
273 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
274 esignal_signo(VALUE self, SEL sel)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
275 {
276 return rb_iv_get(self, "signo");
277 }
278
279 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
280 interrupt_init(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
281 {
282 VALUE args[2];
283
284 args[0] = INT2FIX(SIGINT);
285 rb_scan_args(argc, argv, "01", &args[1]);
286 //return rb_call_super(2, args);
287 return rb_vm_call(self, selInitialize2, 2, args, true);
288 }
289
290 void
291 ruby_default_signal(int sig)
292 {
293 #ifndef MACOS_UNUSE_SIGNAL
294 signal(sig, SIG_DFL);
295 raise(sig);
296 #endif
297 }
298
299 /*
300 * call-seq:
301 * Process.kill(signal, pid, ...) => fixnum
302 *
303 * Sends the given signal to the specified process id(s), or to the
304 * current process if _pid_ is zero. _signal_ may be an
305 * integer signal number or a POSIX signal name (either with or without
306 * a +SIG+ prefix). If _signal_ is negative (or starts
307 * with a minus sign), kills process groups instead of
308 * processes. Not all signals are available on all platforms.
309 *
310 * pid = fork do
311 * Signal.trap("HUP") { puts "Ouch!"; exit }
312 * # ... do some work ...
313 * end
314 * # ...
315 * Process.kill("HUP", pid)
316 * Process.wait
317 *
318 * <em>produces:</em>
319 *
320 * Ouch!
321 */
322
323 VALUE
324 rb_f_kill(int argc, VALUE *argv)
325 {
326 #ifndef HAS_KILLPG
327 #define killpg(pg, sig) kill(-(pg), sig)
328 #endif
329 int negative = 0;
330 int sig;
331 int i;
332 const char *s;
333
334 rb_secure(2);
335 if (argc < 2)
336 rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)");
337 switch (TYPE(argv[0])) {
338 case T_FIXNUM:
339 sig = FIX2INT(argv[0]);
340 break;
341
342 case T_SYMBOL:
343 s = rb_sym2name(argv[0]);
344 if (!s) rb_raise(rb_eArgError, "bad signal");
345 goto str_signal;
346
347 case T_STRING:
348 s = RSTRING_PTR(argv[0]);
349 if (s[0] == '-') {
350 negative++;
351 s++;
352 }
353 str_signal:
354 if (strncmp("SIG", s, 3) == 0)
355 s += 3;
356 if((sig = signm2signo(s)) == 0)
357 rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
358
359 if (negative)
360 sig = -sig;
361 break;
362
363 default:
364 {
365 VALUE str;
366
367 str = rb_check_string_type(argv[0]);
368 if (!NIL_P(str)) {
369 s = RSTRING_PTR(str);
370 goto str_signal;
371 }
372 rb_raise(rb_eArgError, "bad signal type %s",
373 rb_obj_classname(argv[0]));
374 }
375 break;
376 }
377
378 if (sig < 0) {
379 sig = -sig;
380 for (i=1; i<argc; i++) {
381 if (killpg(NUM2PIDT(argv[i]), sig) < 0)
382 rb_sys_fail(0);
383 }
384 }
385 else {
386 for (i=1; i<argc; i++) {
387 if (kill(NUM2PIDT(argv[i]), sig) < 0)
388 rb_sys_fail(0);
389 }
390 }
391 rb_thread_polling();
392 return INT2FIX(i-1);
393 }
394
395 static struct {
396 VALUE cmd;
397 } trap_list[NSIG];
398 static rb_atomic_t trap_pending_list[NSIG];
399 #if 0
400 static char rb_trap_accept_nativethreads[NSIG];
401 #endif
402 rb_atomic_t rb_trap_pending;
403 rb_atomic_t rb_trap_immediate;
404 int rb_prohibit_interrupt = 1;
405
406 VALUE
407 rb_get_trap_cmd(int sig)
408 {
409 return trap_list[sig].cmd;
410 }
411
412 void
413 rb_gc_mark_trap_list(void)
414 {
415 #ifndef MACOS_UNUSE_SIGNAL
416 int i;
417
418 for (i=0; i<NSIG; i++) {
419 if (trap_list[i].cmd)
420 rb_gc_mark(trap_list[i].cmd);
421 }
422 #endif /* MACOS_UNUSE_SIGNAL */
423 }
424
425 #ifdef __dietlibc__
426 #define sighandler_t sh_t
427 #endif
428
429 typedef RETSIGTYPE (*sighandler_t)(int);
430
431 #ifdef POSIX_SIGNAL
432 static sighandler_t
433 ruby_signal(int signum, sighandler_t handler)
434 {
435 struct sigaction sigact, old;
436
437 #if 0
438 rb_trap_accept_nativethreads[signum] = 0;
439 #endif
440
441 sigemptyset(&sigact.sa_mask);
442 #ifdef SA_SIGINFO
443 sigact.sa_sigaction = (void (*)(int, siginfo_t*, void*))handler;
444 sigact.sa_flags = SA_SIGINFO;
445 #else
446 sigact.sa_handler = handler;
447 sigact.sa_flags = 0;
448 #endif
449
450 #ifdef SA_NOCLDWAIT
451 if (signum == SIGCHLD && handler == SIG_IGN)
452 sigact.sa_flags |= SA_NOCLDWAIT;
453 #endif
454 sigaction(signum, &sigact, &old);
455 return old.sa_handler;
456 }
457
458 sighandler_t
459 posix_signal(int signum, sighandler_t handler)
460 {
461 return ruby_signal(signum, handler);
462 }
463
464 #else /* !POSIX_SIGNAL */
465 #define ruby_signal(sig,handler) (/* rb_trap_accept_nativethreads[sig] = 0,*/ signal((sig),(handler)))
466 #if 0 /* def HAVE_NATIVETHREAD */
467 static sighandler_t
468 ruby_nativethread_signal(int signum, sighandler_t handler)
469 {
470 sighandler_t old;
471
472 old = signal(signum, handler);
473 rb_trap_accept_nativethreads[signum] = 1;
474 return old;
475 }
476 #endif
477 #endif
478
479 static RETSIGTYPE
480 sighandler(int sig)
481 {
482 #if 0
483 rb_vm_t *vm = GET_VM(); /* fix me for Multi-VM */
484 ATOMIC_INC(vm->signal_buff[sig]);
485 ATOMIC_INC(vm->buffered_signal_size);
486 #endif
487
488 #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
489 ruby_signal(sig, sighandler);
490 #endif
491 }
492
493 #if USE_TRAP_MASK
494 # ifdef HAVE_SIGPROCMASK
495 static sigset_t trap_last_mask;
496 # else
497 static int trap_last_mask;
498 # endif
499 #endif
500
501 #if HAVE_PTHREAD_H
502 #include <pthread.h>
503 #endif
504
505 void
506 rb_disable_interrupt(void)
507 {
508 #ifndef _WIN32
509 sigset_t mask;
510 sigfillset(&mask);
511 sigdelset(&mask, SIGVTALRM);
512 sigdelset(&mask, SIGSEGV);
513 pthread_sigmask(SIG_SETMASK, &mask, NULL);
514 #endif
515 }
516
517 void
518 rb_enable_interrupt(void)
519 {
520 #ifndef _WIN32
521 sigset_t mask;
522 sigemptyset(&mask);
523 pthread_sigmask(SIG_SETMASK, &mask, NULL);
524 #endif
525 }
526
527 #if 0 // XXX unused function
528 int
529 rb_get_next_signal(rb_vm_t *vm)
530 {
531 int i, sig = 0;
532
533 for (i=1; i<RUBY_NSIG; i++) {
534 if (vm->signal_buff[i] > 0) {
535 rb_disable_interrupt();
536 {
537 ATOMIC_DEC(vm->signal_buff[i]);
538 ATOMIC_DEC(vm->buffered_signal_size);
539 }
540 rb_enable_interrupt();
541 sig = i;
542 break;
543 }
544 }
545 return sig;
546 }
547 #endif
548
549 #ifdef SIGBUS
550 static RETSIGTYPE
551 sigbus(int sig)
552 {
553 rb_bug("Bus Error");
554 }
555 #endif
556
557 #ifdef SIGSEGV
558 static int segv_received = 0;
559 static RETSIGTYPE
560 sigsegv(int sig)
561 {
562 if (segv_received) {
563 fprintf(stderr, "SEGV recieved in SEGV handler\n");
564 exit(1);
565 }
566 else {
567 segv_received = 1;
568 rb_bug("Segmentation fault");
569 }
570 }
571 #endif
572
573 #ifdef SIGPIPE
574 static RETSIGTYPE
575 sigpipe(int sig)
576 {
577 /* do nothing */
578 }
579 #endif
580
581 static void
582 signal_exec(VALUE cmd, int sig)
583 {
584 #if 0 // TODO
585 rb_proc_t *proc;
586 VALUE signum = INT2FIX(sig);
587 GetProcPtr(cmd, proc);
588 vm_invoke_proc(GET_THREAD(), proc, proc->block.self, 1, &signum, 0);
589 #endif
590 }
591
592 void
593 rb_trap_exit(void)
594 {
595 #ifndef MACOS_UNUSE_SIGNAL
596 if (trap_list[0].cmd) {
597 VALUE trap_exit = trap_list[0].cmd;
598
599 trap_list[0].cmd = 0;
600 signal_exec(trap_exit, 0);
601 }
602 #endif
603 }
604
605 static void
606 rb_signal_exec(int sig)
607 {
608 VALUE cmd = rb_get_trap_cmd(sig);
609
610 if (cmd == 0) {
611 switch (sig) {
612 case SIGINT:
613 rb_interrupt();
614 break;
615 #ifdef SIGHUP
616 case SIGHUP:
617 #endif
618 #ifdef SIGQUIT
619 case SIGQUIT:
620 #endif
621 #ifdef SIGTERM
622 case SIGTERM:
623 #endif
624 #ifdef SIGALRM
625 case SIGALRM:
626 #endif
627 #ifdef SIGUSR1
628 case SIGUSR1:
629 #endif
630 #ifdef SIGUSR2
631 case SIGUSR2:
632 #endif
633 //rb_thread_signal_raise(th, sig);
634 break;
635 }
636 }
637 else if (cmd == Qundef) {
638 // rb_thread_signal_exit(th);
639 }
640 else {
641 signal_exec(cmd, sig);
642 }
643 }
644
645 void
646 rb_trap_exec(void)
647 {
648 #ifndef MACOS_UNUSE_SIGNAL
649 int i;
650
651 for (i=0; i<NSIG; i++) {
652 if (trap_pending_list[i]) {
653 trap_pending_list[i] = 0;
654 rb_signal_exec(i);
655 }
656 }
657 #endif /* MACOS_UNUSE_SIGNAL */
658 rb_trap_pending = 0;
659 }
660
661 struct trap_arg {
662 #if USE_TRAP_MASK
663 # ifdef HAVE_SIGPROCMASK
664 sigset_t mask;
665 # else
666 int mask;
667 # endif
668 #endif
669 int sig;
670 sighandler_t func;
671 VALUE cmd;
672 };
673
674 static sighandler_t
675 default_handler(int sig)
676 {
677 sighandler_t func;
678 switch (sig) {
679 case SIGINT:
680 #ifdef SIGHUP
681 case SIGHUP:
682 #endif
683 #ifdef SIGQUIT
684 case SIGQUIT:
685 #endif
686 #ifdef SIGTERM
687 case SIGTERM:
688 #endif
689 #ifdef SIGALRM
690 case SIGALRM:
691 #endif
692 #ifdef SIGUSR1
693 case SIGUSR1:
694 #endif
695 #ifdef SIGUSR2
696 case SIGUSR2:
697 #endif
698 func = sighandler;
699 break;
700 #ifdef SIGBUS
701 case SIGBUS:
702 func = sigbus;
703 break;
704 #endif
705 #ifdef SIGSEGV
706 case SIGSEGV:
707 func = sigsegv;
708 break;
709 #endif
710 #ifdef SIGPIPE
711 case SIGPIPE:
712 func = sigpipe;
713 break;
714 #endif
715 default:
716 func = SIG_DFL;
717 break;
718 }
719
720 return func;
721 }
722
723 static RETSIGTYPE
724 wrong_trap(int sig)
725 {
726 }
727
728 static sighandler_t
729 trap_handler(VALUE *cmd, int sig)
730 {
731 sighandler_t func = wrong_trap;
732 VALUE command;
733
734 if (NIL_P(*cmd)) {
735 func = SIG_IGN;
736 }
737 else {
738 command = rb_check_string_type(*cmd);
739 if (!NIL_P(command)) {
740 SafeStringValue(command); /* taint check */
741 switch (RSTRING_LEN(command)) {
742 case 0:
743 goto sig_ign;
744 break;
745 case 14:
746 if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) {
747 func = SIG_DFL;
748 *cmd = 0;
749 }
750 break;
751 case 7:
752 if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) {
753 sig_ign:
754 func = SIG_IGN;
755 *cmd = 0;
756 }
757 else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
758 sig_dfl:
759 func = default_handler(sig);
760 *cmd = 0;
761 }
762 else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) {
763 goto sig_dfl;
764 }
765 break;
766 case 6:
767 if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) {
768 goto sig_ign;
769 }
770 break;
771 case 4:
772 if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) {
773 func = sighandler;
774 *cmd = Qundef;
775 }
776 break;
777 }
778 if (func == wrong_trap) {
779 rb_raise(rb_eArgError, "wrong trap - %s", RSTRING_PTR(command));
780 }
781 }
782 else {
783 #if 0 // TODO
784 rb_proc_t *proc;
785 GetProcPtr(*cmd, proc);
786 #endif
787 func = sighandler;
788 }
789 }
790
791 return func;
792 }
793
794 static int
795 trap_signm(VALUE vsig)
796 {
797 int sig = -1;
798 const char *s;
799
800 switch (TYPE(vsig)) {
801 case T_FIXNUM:
802 sig = FIX2INT(vsig);
803 if (sig < 0 || sig >= NSIG) {
804 rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
805 }
806 break;
807
808 case T_SYMBOL:
809 s = rb_sym2name(vsig);
810 if (!s) rb_raise(rb_eArgError, "bad signal");
811 goto str_signal;
812
813 default:
814 s = StringValuePtr(vsig);
815
816 str_signal:
817 if (strncmp("SIG", s, 3) == 0)
818 s += 3;
819 sig = signm2signo(s);
820 if (sig == 0 && strcmp(s, "EXIT") != 0)
821 rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
822 }
823 return sig;
824 }
825
826 static VALUE
827 trap(struct trap_arg *arg)
828 {
829 sighandler_t oldfunc, func = arg->func;
830 VALUE oldcmd, command = arg->cmd;
831 int sig = arg->sig;
832
833 oldfunc = ruby_signal(sig, func);
834 oldcmd = trap_list[sig].cmd;
835 switch (oldcmd) {
836 case 0:
837 if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
838 else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
839 else oldcmd = Qnil;
840 break;
841 case Qundef:
842 oldcmd = rb_str_new2("EXIT");
843 break;
844 }
845
846 trap_list[sig].cmd = command;
847 /* enable at least specified signal. */
848 #if USE_TRAP_MASK
849 #ifdef HAVE_SIGPROCMASK
850 sigdelset(&arg->mask, sig);
851 #else
852 arg->mask &= ~sigmask(sig);
853 #endif
854 #endif
855 return oldcmd;
856 }
857
858 #if USE_TRAP_MASK
859 static VALUE
860 trap_ensure(struct trap_arg *arg)
861 {
862 /* enable interrupt */
863 #ifdef HAVE_SIGPROCMASK
864 sigprocmask(SIG_SETMASK, &arg->mask, NULL);
865 #else
866 sigsetmask(arg->mask);
867 #endif
868 trap_last_mask = arg->mask;
869 return 0;
870 }
871 #endif
872
873 void
874 rb_trap_restore_mask(void)
875 {
876 #if USE_TRAP_MASK
877 # ifdef HAVE_SIGPROCMASK
878 sigprocmask(SIG_SETMASK, &trap_last_mask, NULL);
879 # else
880 sigsetmask(trap_last_mask);
881 # endif
882 #endif
883 }
884
885 /*
886 * call-seq:
887 * Signal.trap( signal, command ) => obj
888 * Signal.trap( signal ) {| | block } => obj
889 *
890 * Specifies the handling of signals. The first parameter is a signal
891 * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
892 * signal number. The characters ``SIG'' may be omitted from the
893 * signal name. The command or block specifies code to be run when the
894 * signal is raised.
895 * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
896 * will be ignored.
897 * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
898 * will be invoked.
899 * If the command is ``EXIT'', the script will be terminated by the signal.
900 * If the command is ``SYSTEM_DEFAULT'', the operating system's default
901 * handler will be invoked.
902 * Otherwise, the given command or block will be run.
903 * The special signal name ``EXIT'' or signal number zero will be
904 * invoked just prior to program termination.
905 * trap returns the previous handler for the given signal.
906 *
907 * Signal.trap(0, proc { puts "Terminating: #{$$}" })
908 * Signal.trap("CLD") { puts "Child died" }
909 * fork && Process.wait
910 *
911 * produces:
912 * Terminating: 27461
913 * Child died
914 * Terminating: 27460
915 */
916 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
917 sig_trap(VALUE rcv, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
918 {
919 struct trap_arg arg;
920
921 rb_secure(2);
922 if (argc == 0 || argc > 2) {
923 rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
924 }
925
926 arg.sig = trap_signm(argv[0]);
927 if (argc == 1) {
928 arg.cmd = rb_block_proc();
929 arg.func = sighandler;
930 }
931 else if (argc == 2) {
932 arg.cmd = argv[1];
933 arg.func = trap_handler(&arg.cmd, arg.sig);
934 }
935
936 if (OBJ_TAINTED(arg.cmd)) {
937 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
938 }
939 #if USE_TRAP_MASK
940 /* disable interrupt */
941 # ifdef HAVE_SIGPROCMASK
942 sigfillset(&arg.mask);
943 sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask);
944 # else
945 arg.mask = sigblock(~0);
946 # endif
947
948 return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
949 #else
950 return trap(&arg);
951 #endif
952 }
953
954 /*
955 * call-seq:
956 * Signal.list => a_hash
957 *
958 * Returns a list of signal names mapped to the corresponding
959 * underlying signal numbers.
960 *
961 * 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}
962 */
963 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
964 sig_list(VALUE rcv, SEL sel)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
965 {
966 VALUE h = rb_hash_new();
967 const struct signals *sigs;
968
969 for (sigs = siglist; sigs->signm; sigs++) {
970 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
971 }
972 return h;
973 }
974
975 static void
976 install_sighandler(int signum, sighandler_t handler)
977 {
978 sighandler_t old;
979
980 old = ruby_signal(signum, handler);
981 if (old != SIG_DFL) {
982 ruby_signal(signum, old);
983 }
984 }
985
986 #if defined(SIGCLD) || defined(SIGCHLD)
987 static void
988 init_sigchld(int sig)
989 {
990 sighandler_t oldfunc;
991 #if USE_TRAP_MASK
992 # ifdef HAVE_SIGPROCMASK
993 sigset_t mask;
994 # else
995 int mask;
996 # endif
997 #endif
998
999 #if USE_TRAP_MASK
1000 /* disable interrupt */
1001 # ifdef HAVE_SIGPROCMASK
1002 sigfillset(&mask);
1003 sigprocmask(SIG_BLOCK, &mask, &mask);
1004 # else
1005 mask = sigblock(~0);
1006 # endif
1007 #endif
1008
1009 oldfunc = ruby_signal(sig, SIG_DFL);
1010 if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
1011 ruby_signal(sig, oldfunc);
1012 } else {
1013 trap_list[sig].cmd = 0;
1014 }
1015
1016 #if USE_TRAP_MASK
1017 #ifdef HAVE_SIGPROCMASK
1018 sigdelset(&mask, sig);
1019 sigprocmask(SIG_SETMASK, &mask, NULL);
1020 #else
1021 mask &= ~sigmask(sig);
1022 sigsetmask(mask);
1023 #endif
1024 trap_last_mask = mask;
1025 #endif
1026 }
1027 #endif
1028
1029 void
1030 ruby_sig_finalize()
1031 {
1032 sighandler_t oldfunc;
1033
1034 oldfunc = ruby_signal(SIGINT, SIG_IGN);
1035 if (oldfunc == sighandler) {
1036 ruby_signal(SIGINT, SIG_DFL);
1037 }
1038 }
1039
1040
1041 #ifdef RUBY_DEBUG_ENV
1042 int ruby_enable_coredump = 0;
1043 #endif
1044
1045 /*
1046 * Many operating systems allow signals to be sent to running
1047 * processes. Some signals have a defined effect on the process, while
1048 * others may be trapped at the code level and acted upon. For
1049 * example, your process may trap the USR1 signal and use it to toggle
1050 * debugging, and may use TERM to initiate a controlled shutdown.
1051 *
1052 * pid = fork do
1053 * Signal.trap("USR1") do
1054 * $debug = !$debug
1055 * puts "Debug now: #$debug"
1056 * end
1057 * Signal.trap("TERM") do
1058 * puts "Terminating..."
1059 * shutdown()
1060 * end
1061 * # . . . do some work . . .
1062 * end
1063 *
1064 * Process.detach(pid)
1065 *
1066 * # Controlling program:
1067 * Process.kill("USR1", pid)
1068 * # ...
1069 * Process.kill("USR1", pid)
1070 * # ...
1071 * Process.kill("TERM", pid)
1072 *
1073 * produces:
1074 * Debug now: true
1075 * Debug now: false
1076 * Terminating...
1077 *
1078 * The list of available signal names and their interpretation is
1079 * system dependent. Signal delivery semantics may also vary between
1080 * systems; in particular signal delivery may not always be reliable.
1081 */
1082 void
1083 Init_signal(void)
1084 {
1085 #ifndef MACOS_UNUSE_SIGNAL
1086 VALUE mSignal = rb_define_module("Signal");
1087
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
1088 rb_objc_define_method(rb_mKernel, "trap", sig_trap, -1);
1089 rb_objc_define_method(*(VALUE *)mSignal, "trap", sig_trap, -1);
1090 rb_objc_define_method(*(VALUE *)mSignal, "list", sig_list, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1091
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
1092 rb_objc_define_method(rb_eSignal, "initialize", esignal_init, -1);
1093 rb_objc_define_method(rb_eSignal, "signo", esignal_signo, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1094 rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
1095 rb_objc_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1096
1097 install_sighandler(SIGINT, sighandler);
1098 #ifdef SIGHUP
1099 install_sighandler(SIGHUP, sighandler);
1100 #endif
1101 #ifdef SIGQUIT
1102 install_sighandler(SIGQUIT, sighandler);
1103 #endif
1104 #ifdef SIGTERM
1105 install_sighandler(SIGTERM, sighandler);
1106 #endif
1107 #ifdef SIGALRM
1108 install_sighandler(SIGALRM, sighandler);
1109 #endif
1110 #ifdef SIGUSR1
1111 install_sighandler(SIGUSR1, sighandler);
1112 #endif
1113 #ifdef SIGUSR2
1114 install_sighandler(SIGUSR2, sighandler);
1115 #endif
1116
1117 #ifdef RUBY_DEBUG_ENV
1118 if (!ruby_enable_coredump)
1119 #endif
1120 {
1121 #ifdef SIGBUS
1122 install_sighandler(SIGBUS, sigbus);
1123 #endif
1124 #ifdef SIGSEGV
1125 install_sighandler(SIGSEGV, sigsegv);
1126 #endif
1127 }
1128 #ifdef SIGPIPE
1129 install_sighandler(SIGPIPE, sigpipe);
1130 #endif
1131
1132 #if defined(SIGCLD)
1133 init_sigchld(SIGCLD);
1134 #elif defined(SIGCHLD)
1135 init_sigchld(SIGCHLD);
1136 #endif
1137
1138 #endif /* MACOS_UNUSE_SIGNAL */
1139 }
Something went wrong with that request. Please try again.