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