signal.c
DEFINITIONS
This source file includes following functions.
- signm2signo
- signo2signm
- rb_f_kill
- rb_gc_mark_trap_list
- RETSIGTYPE
- posix_signal
- signal_exec
- sighandler
- sigbus
- sigsegv
- sigpipe
- rb_trap_exit
- rb_trap_exec
- sigexit
- trap
- trap_ensure
- rb_trap_restore_mask
- sig_trap
- sig_list
- install_sighandler
- Init_signal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include "ruby.h"
16 #include "rubysig.h"
17 #include <signal.h>
18 #include <stdio.h>
19
20 #ifdef __BEOS__
21 #undef SIGBUS
22 #endif
23
24 #ifndef NSIG
25 # ifdef DJGPP
26 # define NSIG SIGMAX
27 # else
28 # define NSIG (_SIGMAX + 1)
29 # endif
30 #endif
31
32 static struct signals {
33 char *signm;
34 int signo;
35 } siglist [] = {
36 #ifdef SIGHUP
37 {"HUP", SIGHUP},
38 #endif
39 {"INT", SIGINT},
40 #ifdef SIGQUIT
41 {"QUIT", SIGQUIT},
42 #endif
43 #ifdef SIGILL
44 {"ILL", SIGILL},
45 #endif
46 #ifdef SIGTRAP
47 {"TRAP", SIGTRAP},
48 #endif
49 #ifdef SIGIOT
50 {"IOT", SIGIOT},
51 #endif
52 #ifdef SIGABRT
53 {"ABRT", SIGABRT},
54 #endif
55 #ifdef SIGEMT
56 {"EMT", SIGEMT},
57 #endif
58 #ifdef SIGFPE
59 {"FPE", SIGFPE},
60 #endif
61 #ifdef SIGKILL
62 {"KILL", SIGKILL},
63 #endif
64 #ifdef SIGBUS
65 {"BUS", SIGBUS},
66 #endif
67 #ifdef SIGSEGV
68 {"SEGV", SIGSEGV},
69 #endif
70 #ifdef SIGSYS
71 {"SYS", SIGSYS},
72 #endif
73 #ifdef SIGPIPE
74 {"PIPE", SIGPIPE},
75 #endif
76 #ifdef SIGALRM
77 {"ALRM", SIGALRM},
78 #endif
79 #ifdef SIGTERM
80 {"TERM", SIGTERM},
81 #endif
82 #ifdef SIGURG
83 {"URG", SIGURG},
84 #endif
85 #ifdef SIGSTOP
86 {"STOP", SIGSTOP},
87 #endif
88 #ifdef SIGTSTP
89 {"TSTP", SIGTSTP},
90 #endif
91 #ifdef SIGCONT
92 {"CONT", SIGCONT},
93 #endif
94 #ifdef SIGCHLD
95 {"CHLD", SIGCHLD},
96 #endif
97 #ifdef SIGCLD
98 {"CLD", SIGCLD},
99 #else
100 # ifdef SIGCHLD
101 {"CLD", SIGCHLD},
102 # endif
103 #endif
104 #ifdef SIGTTIN
105 {"TTIN", SIGTTIN},
106 #endif
107 #ifdef SIGTTOU
108 {"TTOU", SIGTTOU},
109 #endif
110 #ifdef SIGIO
111 {"IO", SIGIO},
112 #endif
113 #ifdef SIGXCPU
114 {"XCPU", SIGXCPU},
115 #endif
116 #ifdef SIGXFSZ
117 {"XFSZ", SIGXFSZ},
118 #endif
119 #ifdef SIGVTALRM
120 {"VTALRM", SIGVTALRM},
121 #endif
122 #ifdef SIGPROF
123 {"PROF", SIGPROF},
124 #endif
125 #ifdef SIGWINCH
126 {"WINCH", SIGWINCH},
127 #endif
128 #ifdef SIGUSR1
129 {"USR1", SIGUSR1},
130 #endif
131 #ifdef SIGUSR2
132 {"USR2", SIGUSR2},
133 #endif
134 #ifdef SIGLOST
135 {"LOST", SIGLOST},
136 #endif
137 #ifdef SIGMSG
138 {"MSG", SIGMSG},
139 #endif
140 #ifdef SIGPWR
141 {"PWR", SIGPWR},
142 #endif
143 #ifdef SIGPOLL
144 {"POLL", SIGPOLL},
145 #endif
146 #ifdef SIGDANGER
147 {"DANGER", SIGDANGER},
148 #endif
149 #ifdef SIGMIGRATE
150 {"MIGRATE", SIGMIGRATE},
151 #endif
152 #ifdef SIGPRE
153 {"PRE", SIGPRE},
154 #endif
155 #ifdef SIGGRANT
156 {"GRANT", SIGGRANT},
157 #endif
158 #ifdef SIGRETRACT
159 {"RETRACT", SIGRETRACT},
160 #endif
161 #ifdef SIGSOUND
162 {"SOUND", SIGSOUND},
163 #endif
164 #ifdef SIGINFO
165 {"INFO", SIGINFO},
166 #endif
167 {NULL, 0}
168 };
169
170 static int
171 signm2signo(nm)
172 char *nm;
173 {
174 struct signals *sigs;
175
176 for (sigs = siglist; sigs->signm; sigs++)
177 if (strcmp(sigs->signm, nm) == 0)
178 return sigs->signo;
179 return 0;
180 }
181
182 static char*
183 signo2signm(no)
184 int no;
185 {
186 struct signals *sigs;
187
188 for (sigs = siglist; sigs->signm; sigs++)
189 if (sigs->signo == no)
190 return sigs->signm;
191 return 0;
192 }
193
194 VALUE
195 rb_f_kill(argc, argv)
196 int argc;
197 VALUE *argv;
198 {
199 int negative = 0;
200 int sig;
201 int i;
202 char *s;
203
204 rb_secure(2);
205 if (argc < 2)
206 rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)");
207 switch (TYPE(argv[0])) {
208 case T_FIXNUM:
209 sig = FIX2INT(argv[0]);
210 break;
211
212 case T_SYMBOL:
213 s = rb_id2name(SYM2ID(argv[0]));
214 if (!s) rb_raise(rb_eArgError, "bad signal");
215 goto str_signal;
216
217 case T_STRING:
218 s = RSTRING(argv[0])->ptr;
219 if (s[0] == '-') {
220 negative++;
221 s++;
222 }
223 str_signal:
224 if (strncmp("SIG", s, 3) == 0)
225 s += 3;
226 if((sig = signm2signo(s)) == 0)
227 rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
228
229 if (negative)
230 sig = -sig;
231 break;
232
233 default:
234 {
235 VALUE str;
236
237 str = rb_check_convert_type(argv[0], T_STRING, "String", "to_str");
238 if (!NIL_P(str)) {
239 s = RSTRING(str)->ptr;
240 goto str_signal;
241 }
242 rb_raise(rb_eArgError, "bad signal type %s",
243 rb_class2name(CLASS_OF(argv[0])));
244 }
245 break;
246 }
247
248 if (sig < 0) {
249 sig = -sig;
250 for (i=1; i<argc; i++) {
251 int pid = NUM2INT(argv[i]);
252 #ifdef HAS_KILLPG
253 if (killpg(pid, sig) < 0)
254 #else
255 if (kill(-pid, sig) < 0)
256 #endif
257 rb_sys_fail(0);
258 }
259 }
260 else {
261 for (i=1; i<argc; i++) {
262 Check_Type(argv[i], T_FIXNUM);
263 if (kill(FIX2INT(argv[i]), sig) < 0)
264 rb_sys_fail(0);
265 }
266 }
267 return INT2FIX(i-1);
268 }
269
270 static VALUE trap_list[NSIG];
271 static rb_atomic_t trap_pending_list[NSIG];
272 rb_atomic_t rb_trap_pending;
273 rb_atomic_t rb_trap_immediate;
274 int rb_prohibit_interrupt;
275
276 void
277 rb_gc_mark_trap_list()
278 {
279 #ifndef MACOS_UNUSE_SIGNAL
280 int i;
281
282 for (i=0; i<NSIG; i++) {
283 if (trap_list[i])
284 rb_gc_mark(trap_list[i]);
285 }
286 #endif
287 }
288
289 #ifdef __dietlibc__
290 #define sighandler_t sh_t
291 #endif
292
293 typedef RETSIGTYPE (*sighandler_t)_((int));
294
295 #ifdef POSIX_SIGNAL
296 static sighandler_t
297 ruby_signal(signum, handler)
298 int signum;
299 sighandler_t handler;
300 {
301 struct sigaction sigact, old;
302
303 sigact.sa_handler = handler;
304 sigemptyset(&sigact.sa_mask);
305 sigact.sa_flags = 0;
306 #if defined(SA_RESTART)
307
308
309
310 if (signum != SIGVTALRM) {
311 sigact.sa_flags |= SA_RESTART;
312 }
313 #endif
314 #ifdef SA_NOCLDWAIT
315 if (signum == SIGCHLD && handler == SIG_IGN)
316 sigact.sa_flags |= SA_NOCLDWAIT;
317 #endif
318 sigaction(signum, &sigact, &old);
319 return old.sa_handler;
320 }
321
322 void
323 posix_signal(signum, handler)
324 int signum;
325 sighandler_t handler;
326 {
327 ruby_signal(signum, handler);
328 }
329 #else
330 #define ruby_signal(sig,handler) signal((sig),(handler))
331 #endif
332
333 static void signal_exec _((int sig));
334 static void
335 signal_exec(sig)
336 int sig;
337 {
338 if (trap_list[sig] == 0) {
339 switch (sig) {
340 case SIGINT:
341 rb_thread_interrupt();
342 break;
343 #ifdef SIGHUP
344 case SIGHUP:
345 #endif
346 #ifdef SIGQUIT
347 case SIGQUIT:
348 #endif
349 #ifdef SIGALRM
350 case SIGALRM:
351 #endif
352 #ifdef SIGUSR1
353 case SIGUSR1:
354 #endif
355 #ifdef SIGUSR2
356 case SIGUSR2:
357 #endif
358 rb_thread_signal_raise(signo2signm(sig));
359 break;
360 }
361 }
362 else {
363 rb_thread_trap_eval(trap_list[sig], sig);
364 }
365 }
366
367 static RETSIGTYPE sighandler _((int));
368 static RETSIGTYPE
369 sighandler(sig)
370 int sig;
371 {
372 #ifdef NT
373 #define IN_MAIN_CONTEXT(f, a) (rb_w32_main_context(a, f) ? (void)0 : f(a))
374 #else
375 #define IN_MAIN_CONTEXT(f, a) f(a)
376 #endif
377
378 if (sig >= NSIG) {
379 rb_bug("trap_handler: Bad signal %d", sig);
380 }
381
382 #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
383 ruby_signal(sig, sighandler);
384 #endif
385
386 if (ATOMIC_TEST(rb_trap_immediate)) {
387 IN_MAIN_CONTEXT(signal_exec, sig);
388 ATOMIC_SET(rb_trap_immediate, 1);
389 }
390 else {
391 ATOMIC_INC(rb_trap_pending);
392 ATOMIC_INC(trap_pending_list[sig]);
393 }
394 }
395
396 #ifdef SIGBUS
397 static RETSIGTYPE sigbus _((int));
398 static RETSIGTYPE
399 sigbus(sig)
400 int sig;
401 {
402 rb_bug("Bus Error");
403 }
404 #endif
405
406 #ifdef SIGSEGV
407 static RETSIGTYPE sigsegv _((int));
408 static RETSIGTYPE
409 sigsegv(sig)
410 int sig;
411 {
412 rb_bug("Segmentation fault");
413 }
414 #endif
415
416 #ifdef SIGPIPE
417 static RETSIGTYPE sigpipe _((int));
418 static RETSIGTYPE
419 sigpipe(sig)
420 int sig;
421 {
422
423 }
424 #endif
425
426 void
427 rb_trap_exit()
428 {
429 #ifndef MACOS_UNUSE_SIGNAL
430 if (trap_list[0]) {
431 VALUE trap_exit = trap_list[0];
432
433 trap_list[0] = 0;
434 rb_eval_cmd(trap_exit, rb_ary_new3(1, INT2FIX(0)), 0);
435 }
436 #endif
437 }
438
439 void
440 rb_trap_exec()
441 {
442 #ifndef MACOS_UNUSE_SIGNAL
443 int i;
444
445 for (i=0; i<NSIG; i++) {
446 if (trap_pending_list[i]) {
447 trap_pending_list[i] = 0;
448 signal_exec(i);
449 }
450 }
451 #endif
452 rb_trap_pending = 0;
453 }
454
455 struct trap_arg {
456 #if !defined(NT)
457 # ifdef HAVE_SIGPROCMASK
458 sigset_t mask;
459 # else
460 int mask;
461 # endif
462 #endif
463 VALUE sig, cmd;
464 };
465
466 # ifdef HAVE_SIGPROCMASK
467 static sigset_t trap_last_mask;
468 # else
469 static int trap_last_mask;
470 # endif
471
472 static RETSIGTYPE sigexit _((int));
473 static RETSIGTYPE
474 sigexit(sig)
475 int sig;
476 {
477 rb_exit(0);
478 }
479
480 static VALUE
481 trap(arg)
482 struct trap_arg *arg;
483 {
484 sighandler_t func;
485 VALUE command, old;
486 int sig = -1;
487 char *s;
488
489 func = sighandler;
490 command = arg->cmd;
491 if (NIL_P(command)) {
492 func = SIG_IGN;
493 }
494 else if (TYPE(command) == T_STRING) {
495 SafeStringValue(command);
496 if (RSTRING(command)->len == 0) {
497 func = SIG_IGN;
498 }
499 else if (RSTRING(command)->len == 7) {
500 if (strncmp(RSTRING(command)->ptr, "SIG_IGN", 7) == 0) {
501 func = SIG_IGN;
502 }
503 else if (strncmp(RSTRING(command)->ptr, "SIG_DFL", 7) == 0) {
504 func = SIG_DFL;
505 }
506 else if (strncmp(RSTRING(command)->ptr, "DEFAULT", 7) == 0) {
507 func = SIG_DFL;
508 }
509 }
510 else if (RSTRING(command)->len == 6) {
511 if (strncmp(RSTRING(command)->ptr, "IGNORE", 6) == 0) {
512 func = SIG_IGN;
513 }
514 }
515 else if (RSTRING(command)->len == 4) {
516 if (strncmp(RSTRING(command)->ptr, "EXIT", 4) == 0) {
517 func = sigexit;
518 }
519 }
520 }
521 if (func == SIG_IGN || func == SIG_DFL) {
522 command = 0;
523 }
524
525 switch (TYPE(arg->sig)) {
526 case T_FIXNUM:
527 sig = NUM2INT(arg->sig);
528 break;
529
530 case T_SYMBOL:
531 s = rb_id2name(SYM2ID(arg->sig));
532 if (!s) rb_raise(rb_eArgError, "bad signal");
533 goto str_signal;
534
535 case T_STRING:
536 s = RSTRING(arg->sig)->ptr;
537
538 str_signal:
539 if (strncmp("SIG", s, 3) == 0)
540 s += 3;
541 sig = signm2signo(s);
542 if (sig == 0 && strcmp(s, "EXIT") != 0)
543 rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
544 }
545
546 if (sig < 0 || sig > NSIG) {
547 rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
548 }
549 #if defined(HAVE_SETITIMER) && !defined(__BOW__)
550 if (sig == SIGVTALRM) {
551 rb_raise(rb_eArgError, "SIGVTALRM reserved for Thread; cannot set handler");
552 }
553 #endif
554 if (func == SIG_DFL) {
555 switch (sig) {
556 case SIGINT:
557 #ifdef SIGHUP
558 case SIGHUP:
559 #endif
560 #ifdef SIGQUIT
561 case SIGQUIT:
562 #endif
563 #ifdef SIGALRM
564 case SIGALRM:
565 #endif
566 #ifdef SIGUSR1
567 case SIGUSR1:
568 #endif
569 #ifdef SIGUSR2
570 case SIGUSR2:
571 #endif
572 func = sighandler;
573 break;
574 #ifdef SIGBUS
575 case SIGBUS:
576 func = sigbus;
577 break;
578 #endif
579 #ifdef SIGSEGV
580 case SIGSEGV:
581 func = sigsegv;
582 break;
583 #endif
584 #ifdef SIGPIPE
585 case SIGPIPE:
586 func = sigpipe;
587 break;
588 #endif
589 }
590 }
591 ruby_signal(sig, func);
592 old = trap_list[sig];
593 if (!old) old = Qnil;
594
595 trap_list[sig] = command;
596
597 #if !defined(NT)
598 #ifdef HAVE_SIGPROCMASK
599 sigdelset(&arg->mask, sig);
600 #else
601 arg->mask &= ~sigmask(sig);
602 #endif
603 #endif
604 return old;
605 }
606
607 #if !defined(NT)
608 static VALUE
609 trap_ensure(arg)
610 struct trap_arg *arg;
611 {
612
613 #ifdef HAVE_SIGPROCMASK
614 sigprocmask(SIG_SETMASK, &arg->mask, NULL);
615 #else
616 sigsetmask(arg->mask);
617 #endif
618 trap_last_mask = arg->mask;
619 return 0;
620 }
621 #endif
622
623 void
624 rb_trap_restore_mask()
625 {
626 #if !defined(NT)
627 # ifdef HAVE_SIGPROCMASK
628 sigprocmask(SIG_SETMASK, &trap_last_mask, NULL);
629 # else
630 sigsetmask(trap_last_mask);
631 # endif
632 #endif
633 }
634
635 static VALUE
636 sig_trap(argc, argv)
637 int argc;
638 VALUE *argv;
639 {
640 struct trap_arg arg;
641
642 rb_secure(2);
643 if (argc == 0 || argc > 2) {
644 rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
645 }
646
647 arg.sig = argv[0];
648 if (argc == 1) {
649 arg.cmd = rb_f_lambda();
650 }
651 else if (argc == 2) {
652 arg.cmd = argv[1];
653 }
654
655 if (OBJ_TAINTED(arg.cmd)) {
656 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
657 }
658 #if !defined(NT)
659
660 # ifdef HAVE_SIGPROCMASK
661 sigfillset(&arg.mask);
662 sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask);
663 # else
664 arg.mask = sigblock(~0);
665 # endif
666
667 return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
668 #else
669 return trap(&arg);
670 #endif
671 }
672
673 static VALUE
674 sig_list()
675 {
676 VALUE h = rb_hash_new();
677 struct signals *sigs;
678
679 for (sigs = siglist; sigs->signm; sigs++) {
680 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
681 }
682 return h;
683 }
684
685 static void
686 install_sighandler(signum, handler)
687 int signum;
688 sighandler_t handler;
689 {
690 sighandler_t old;
691
692 old = ruby_signal(signum, handler);
693 if (old != SIG_DFL) {
694 ruby_signal(signum, old);
695 }
696 }
697
698 void
699 Init_signal()
700 {
701 #ifndef MACOS_UNUSE_SIGNAL
702 VALUE mSignal = rb_define_module("Signal");
703
704 rb_define_global_function("trap", sig_trap, -1);
705 rb_define_module_function(mSignal, "trap", sig_trap, -1);
706 rb_define_module_function(mSignal, "list", sig_list, 0);
707
708 install_sighandler(SIGINT, sighandler);
709 #ifdef SIGHUP
710 install_sighandler(SIGHUP, sighandler);
711 #endif
712 #ifdef SIGQUIT
713 install_sighandler(SIGQUIT, sighandler);
714 #endif
715 #ifdef SIGALRM
716 install_sighandler(SIGALRM, sighandler);
717 #endif
718 #ifdef SIGUSR1
719 install_sighandler(SIGUSR1, sighandler);
720 #endif
721 #ifdef SIGUSR2
722 install_sighandler(SIGUSR2, sighandler);
723 #endif
724
725 #ifdef SIGBUS
726 install_sighandler(SIGBUS, sigbus);
727 #endif
728 #ifdef SIGSEGV
729 install_sighandler(SIGSEGV, sigsegv);
730 #endif
731 #ifdef SIGPIPE
732 install_sighandler(SIGPIPE, sigpipe);
733 #endif
734 #endif
735 }