Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 790 lines (703 sloc) 17.905 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
153d145 don't install stupid handlers on some signals
Laurent Sansonetti authored
14 // TODO: rewrite me!
15
9c1d230 committing experimental branch content
Laurent Sansonetti authored
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
20 #include "vm.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored
21 #include <signal.h>
22 #include <stdio.h>
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
23 #include <dispatch/dispatch.h>
24 #include <dispatch/queue.h>
9c1d230 committing experimental branch content
Laurent Sansonetti authored
25
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
26 #define USE_DEFAULT_HANDLER (void (*)(int))-1
9c1d230 committing experimental branch content
Laurent Sansonetti authored
27
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
28 static RETSIGTYPE sighandler(int sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
29
30 static const struct signals {
31 const char *signm;
32 int signo;
33 } siglist [] = {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
34 {"EXIT", 0},
35 {"HUP", SIGHUP},
36 {"INT", SIGINT},
37 {"QUIT", SIGQUIT},
38 {"ILL", SIGILL},
39 {"TRAP", SIGTRAP},
40 {"IOT", SIGIOT},
41 {"ABRT", SIGABRT},
42 {"EMT", SIGEMT},
43 {"FPE", SIGFPE},
44 {"KILL", SIGKILL},
45 {"BUS", SIGBUS},
46 {"SEGV", SIGSEGV},
47 {"SYS", SIGSYS},
48 {"PIPE", SIGPIPE},
49 {"ALRM", SIGALRM},
50 {"TERM", SIGTERM},
51 {"URG", SIGURG},
52 {"STOP", SIGSTOP},
53 {"TSTP", SIGTSTP},
54 {"CONT", SIGCONT},
55 {"CHLD", SIGCHLD},
56 {"CLD", SIGCHLD},
57 {"TTIN", SIGTTIN},
58 {"TTOU", SIGTTOU},
59 {"IO", SIGIO},
60 {"XCPU", SIGXCPU},
61 {"XFSZ", SIGXFSZ},
9c1d230 committing experimental branch content
Laurent Sansonetti authored
62 {"VTALRM", SIGVTALRM},
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
63 {"PROF", SIGPROF},
64 {"WINCH", SIGWINCH},
65 {"INFO", SIGINFO},
66 {"USR1", SIGUSR1},
67 {"USR2", SIGUSR2},
9c1d230 committing experimental branch content
Laurent Sansonetti authored
68 {NULL, 0}
69 };
70
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
71 static const struct trap_handlers {
72 const char *command;
73 VALUE new_cmd_value;
74 sighandler_t handler;
75 } gl_trap_handlers[] = {
76 {"SYSTEM_DEFAULT", 0, SIG_DFL},
77 {"SIG_IGN", 0, SIG_IGN},
78 {"IGNORE", 0, SIG_IGN},
79 {"", 0, SIG_IGN},
80 {"SIG_DFL", 0, USE_DEFAULT_HANDLER},
81 {"DEFAULT", 0, USE_DEFAULT_HANDLER},
82 {"EXIT", Qundef, sighandler},
83 {NULL, 0}
84 };
85
9c1d230 committing experimental branch content
Laurent Sansonetti authored
86 static int
87 signm2signo(const char *nm)
88 {
89 const struct signals *sigs;
90
91 for (sigs = siglist; sigs->signm; sigs++)
92 if (strcmp(sigs->signm, nm) == 0)
93 return sigs->signo;
94 return 0;
95 }
96
97 static const char*
98 signo2signm(int no)
99 {
100 const struct signals *sigs;
101
102 for (sigs = siglist; sigs->signm; sigs++)
103 if (sigs->signo == no)
104 return sigs->signm;
105 return 0;
106 }
107
108 const char *
109 ruby_signal_name(int no)
110 {
111 return signo2signm(no);
112 }
113
114 /*
115 * call-seq:
116 * SignalException.new(sig) => signal_exception
117 *
118 * Construct a new SignalException object. +sig+ should be a known
119 * signal name, or a signal number.
120 */
121
122 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
123 esignal_init(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
124 {
125 int argnum = 1;
126 VALUE sig = Qnil;
127 int signo;
128 const char *signm;
129
130 if (argc > 0) {
131 sig = rb_check_to_integer(argv[0], "to_int");
132 if (!NIL_P(sig)) argnum = 2;
133 else sig = argv[0];
134 }
135 if (argc < 1 || argnum < argc) {
136 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
137 argc, argnum);
138 }
139 if (argnum == 2) {
140 signo = NUM2INT(sig);
141 if (signo < 0 || signo > NSIG) {
142 rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
143 }
144 if (argc > 1) {
145 sig = argv[1];
146 }
147 else {
148 signm = signo2signm(signo);
149 if (signm) {
150 sig = rb_sprintf("SIG%s", signm);
151 }
152 else {
153 sig = rb_sprintf("SIG%u", signo);
154 }
155 }
156 }
157 else {
158 signm = SYMBOL_P(sig) ? rb_sym2name(sig) : StringValuePtr(sig);
159 if (strncmp(signm, "SIG", 3) == 0) signm += 3;
160 signo = signm2signo(signm);
161 if (!signo) {
162 rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
163 }
164 sig = rb_sprintf("SIG%s", signm);
165 }
166 //rb_call_super(1, &sig);
167 rb_vm_call(self, selInitialize2, 1, &sig, true);
168 rb_iv_set(self, "signo", INT2NUM(signo));
169
170 return self;
171 }
172
173 /*
174 * call-seq:
175 * signal_exception.signo => num
176 *
177 * Returns a signal number.
178 */
179
180 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
181 esignal_signo(VALUE self, SEL sel)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
182 {
183 return rb_iv_get(self, "signo");
184 }
185
186 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
187 interrupt_init(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
188 {
189 VALUE args[2];
190
191 args[0] = INT2FIX(SIGINT);
192 rb_scan_args(argc, argv, "01", &args[1]);
193 return rb_vm_call(self, selInitialize2, 2, args, true);
194 }
195
196 void
197 ruby_default_signal(int sig)
198 {
199 #ifndef MACOS_UNUSE_SIGNAL
200 signal(sig, SIG_DFL);
201 raise(sig);
202 #endif
203 }
204
205 /*
206 * call-seq:
207 * Process.kill(signal, pid, ...) => fixnum
208 *
209 * Sends the given signal to the specified process id(s), or to the
210 * current process if _pid_ is zero. _signal_ may be an
211 * integer signal number or a POSIX signal name (either with or without
212 * a +SIG+ prefix). If _signal_ is negative (or starts
213 * with a minus sign), kills process groups instead of
214 * processes. Not all signals are available on all platforms.
215 *
216 * pid = fork do
217 * Signal.trap("HUP") { puts "Ouch!"; exit }
218 * # ... do some work ...
219 * end
220 * # ...
221 * Process.kill("HUP", pid)
222 * Process.wait
223 *
224 * <em>produces:</em>
225 *
226 * Ouch!
227 */
228
229 VALUE
e53e3cb ported process.c to the new runtime API
Laurent Sansonetti authored
230 rb_f_kill(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
231 {
232 int negative = 0;
233 int sig;
234 int i;
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
235 int type;
236 const char *s = NULL;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
237
238 rb_secure(2);
239 if (argc < 2)
240 rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)");
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
241
242 type = TYPE(argv[0]);
243 if (type == T_FIXNUM) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
244 sig = FIX2INT(argv[0]);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
245 }
246 else {
247 if (type == T_SYMBOL) {
248 s = rb_sym2name(argv[0]);
249 if (!s)
250 rb_raise(rb_eArgError, "bad signal");
9c1d230 committing experimental branch content
Laurent Sansonetti authored
251 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
252 else if (type == T_STRING) {
253 s = RSTRING_PTR(argv[0]);
254 if (s[0] == '-') {
255 negative++;
256 s++;
257 }
258 }
259 else {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
260 VALUE str;
261 str = rb_check_string_type(argv[0]);
262 if (!NIL_P(str)) {
263 s = RSTRING_PTR(str);
264 }
265 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
266 if (s == NULL)
267 rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0]));
268
269 if (strncmp("SIG", s, 3) == 0)
270 s += 3;
271 if ((sig = signm2signo(s)) == 0)
272 rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
273 if (negative)
274 sig = -sig;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
275 }
276
277 if (sig < 0) {
278 sig = -sig;
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
279 for (i = 1; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
280 if (killpg(NUM2PIDT(argv[i]), sig) < 0)
281 rb_sys_fail(0);
282 }
283 }
284 else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
285 for (i = 1; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
286 if (kill(NUM2PIDT(argv[i]), sig) < 0)
287 rb_sys_fail(0);
288 }
289 }
290 rb_thread_polling();
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
291 return INT2FIX(i - 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
292 }
293
294 rb_atomic_t rb_trap_pending;
295 rb_atomic_t rb_trap_immediate;
296 int rb_prohibit_interrupt = 1;
297
298 VALUE
299 rb_get_trap_cmd(int sig)
300 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
301 return rb_vm_trap_cmd_for_signal(sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
302 }
303
304 void
305 rb_gc_mark_trap_list(void)
306 {
307 #ifndef MACOS_UNUSE_SIGNAL
308 int i;
309
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
310 for (i = 0; i < NSIG; i++) {
311 if (rb_vm_trap_cmd_for_signal(i)) {
312 rb_gc_mark(rb_vm_trap_cmd_for_signal(i));
0c5e41a Courtesy of Jordan Breeding, a patch to build with Clang and llvm-gcc…
Patrick Thomson authored
313 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
314 }
315 #endif /* MACOS_UNUSE_SIGNAL */
316 }
317
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
318 sighandler_t
9c1d230 committing experimental branch content
Laurent Sansonetti authored
319 ruby_signal(int signum, sighandler_t handler)
320 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
321 struct sigaction sigact;
322 struct sigaction old;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
323
324 sigemptyset(&sigact.sa_mask);
325 sigact.sa_handler = handler;
326 sigact.sa_flags = 0;
327
328 if (signum == SIGCHLD && handler == SIG_IGN)
329 sigact.sa_flags |= SA_NOCLDWAIT;
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
330 if (signum == SIGSEGV)
331 sigact.sa_flags |= SA_ONSTACK;
332 if (sigaction(signum, &sigact, &old) < 0) {
333 if (errno != 0 && errno != EINVAL) {
334 rb_bug("sigaction error.\n");
335 }
336 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
337 return old.sa_handler;
338 }
339
340 sighandler_t
341 posix_signal(int signum, sighandler_t handler)
342 {
343 return ruby_signal(signum, handler);
344 }
345
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
346 static void signal_exec(VALUE cmd, int level, int sig);
347 static void rb_signal_exec(int sig);
348
9c1d230 committing experimental branch content
Laurent Sansonetti authored
349 static RETSIGTYPE
350 sighandler(int sig)
351 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
352 int olderrno = errno;
353 rb_signal_exec(sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
354 ruby_signal(sig, sighandler);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
355 errno = olderrno;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
356 }
357
358 #include <pthread.h>
359
360 void
361 rb_disable_interrupt(void)
362 {
363 sigset_t mask;
364 sigfillset(&mask);
365 sigdelset(&mask, SIGVTALRM);
366 sigdelset(&mask, SIGSEGV);
367 pthread_sigmask(SIG_SETMASK, &mask, NULL);
368 }
369
370 void
371 rb_enable_interrupt(void)
372 {
373 sigset_t mask;
374 sigemptyset(&mask);
375 pthread_sigmask(SIG_SETMASK, &mask, NULL);
376 }
377
378 static RETSIGTYPE
379 sigbus(int sig)
380 {
381 rb_bug("Bus Error");
382 }
383
384 static int segv_received = 0;
385 static RETSIGTYPE
386 sigsegv(int sig)
387 {
388 if (segv_received) {
389 fprintf(stderr, "SEGV recieved in SEGV handler\n");
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
390 exit(EXIT_FAILURE);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
391 }
392 else {
393 segv_received = 1;
394 rb_bug("Segmentation fault");
395 }
396 }
397
398 static RETSIGTYPE
399 sigpipe(int sig)
400 {
401 /* do nothing */
402 }
403
404 static void
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
405 signal_exec(VALUE cmd, int level, int sig)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
406 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
407 VALUE signum = INT2NUM(sig);
408 rb_eval_cmd(cmd, rb_ary_new3(1, signum), level);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
409 }
410
411 void
412 rb_trap_exit(void)
413 {
414 #ifndef MACOS_UNUSE_SIGNAL
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
415 VALUE trap_exit;
416 int safe;
417
418 trap_exit = rb_vm_trap_cmd_for_signal(0);
419 if (trap_exit != (VALUE)NULL) {
420 safe = rb_vm_trap_level_for_signal(0);
421 rb_vm_set_trap_for_signal((VALUE)0, safe, 0);
422 signal_exec(trap_exit, safe, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
423 }
424 #endif
425 }
426
427 static void
428 rb_signal_exec(int sig)
429 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
430 /* rb_vm_thread_t *t; */
431 /* VALUE exc; */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
432 VALUE cmd = rb_get_trap_cmd(sig);
433
434 if (cmd == 0) {
435 switch (sig) {
436 case SIGINT:
437 rb_interrupt();
438 break;
439 case SIGHUP:
440 case SIGQUIT:
441 case SIGTERM:
442 case SIGALRM:
443 case SIGUSR1:
444 case SIGUSR2:
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
445 /* t = GetThreadPtr(rb_vm_main_thread()); */
446 /* exc = rb_exc_new2(rb_eSignal, ruby_signal_name(sig)); */
447 /* rb_vm_thread_raise(t, exc); */
448 /* rb_raise(rb_eSignal, "%s", signo2signm(sig)); */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
449 break;
450 }
451 }
452 else if (cmd == Qundef) {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
453 //rb_thread_signal_exit(th);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
454 }
455 else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
456 signal_exec(cmd, rb_vm_trap_level_for_signal(sig), sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
457 }
458 }
459
460 struct trap_arg {
461 int sig;
462 sighandler_t func;
463 VALUE cmd;
464 };
465
466 static sighandler_t
467 default_handler(int sig)
468 {
469 sighandler_t func;
470 switch (sig) {
471 case SIGINT:
472 case SIGHUP:
473 case SIGQUIT:
474 case SIGTERM:
475 case SIGALRM:
476 case SIGUSR1:
477 case SIGUSR2:
478 func = sighandler;
479 break;
480 case SIGBUS:
481 func = sigbus;
482 break;
483 case SIGSEGV:
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
484 func = (sighandler_t)sigsegv;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
485 break;
486 case SIGPIPE:
487 func = sigpipe;
488 break;
489 default:
490 func = SIG_DFL;
491 break;
492 }
493
494 return func;
495 }
496
497 static sighandler_t
498 trap_handler(VALUE *cmd, int sig)
499 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
500 sighandler_t func = sighandler;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
501 VALUE command;
502
503 if (NIL_P(*cmd)) {
504 func = SIG_IGN;
505 }
506 else {
507 command = rb_check_string_type(*cmd);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
508 if (NIL_P(command) && SYMBOL_P(*cmd)) {
509 command = rb_id2str(SYM2ID(*cmd));
510 if (!command) rb_raise(rb_eArgError, "bad handler");
511 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
512 if (!NIL_P(command)) {
513 SafeStringValue(command); /* taint check */
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
514 *cmd = command;
515 for (int i = 0; gl_trap_handlers[i].command != NULL; i++) {
516 if (strcmp(gl_trap_handlers[i].command, RSTRING_PTR(command)) == 0) {
517 func = gl_trap_handlers[i].handler;
518 if (func == USE_DEFAULT_HANDLER) {
519 func = default_handler(sig);
520 }
521 *cmd = gl_trap_handlers[i].new_cmd_value;
522 break;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
523 }
524 }
525 }
526 else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
527 /* func = sighandler; */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
528 }
529 }
530
531 return func;
532 }
533
534 static int
535 trap_signm(VALUE vsig)
536 {
537 int sig = -1;
538 const char *s;
539
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
540 if (TYPE(vsig) == T_FIXNUM) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
541 sig = FIX2INT(vsig);
542 if (sig < 0 || sig >= NSIG) {
543 rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
544 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
545 }
546 else {
547 if (TYPE(vsig) == T_SYMBOL) {
548 s = rb_sym2name(vsig);
549 if (s == NULL)
550 rb_raise(rb_eArgError, "bad signal");
551 }
552 else
553 s = StringValuePtr(vsig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
554
555 if (strncmp("SIG", s, 3) == 0)
556 s += 3;
557 sig = signm2signo(s);
558 if (sig == 0 && strcmp(s, "EXIT") != 0)
559 rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
560 }
561 return sig;
562 }
563
564 static VALUE
565 trap(struct trap_arg *arg)
566 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
567 sighandler_t oldfunc;
568 sighandler_t func = arg->func;
569 VALUE oldcmd;
570 VALUE command = arg->cmd;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
571 int sig = arg->sig;
572
573 oldfunc = ruby_signal(sig, func);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
574 oldcmd = rb_vm_trap_cmd_for_signal(sig);
575 if (oldcmd == 0) {
576 if (oldfunc == SIG_IGN)
577 oldcmd = rb_str_new2("IGNORE");
578 else if (oldfunc == sighandler)
579 oldcmd = rb_str_new2("DEFAULT");
580 else
581 oldcmd = Qnil;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
582 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
583 else if (oldcmd == Qundef)
584 oldcmd = rb_str_new2("EXIT");
9c1d230 committing experimental branch content
Laurent Sansonetti authored
585
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
586 // Assign trap to signal
587 rb_vm_set_trap_for_signal(command, rb_safe_level(), sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
588
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
589 return oldcmd;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
590 }
591
592 void
593 rb_trap_restore_mask(void)
594 {
595 }
596
597 /*
598 * call-seq:
599 * Signal.trap( signal, command ) => obj
600 * Signal.trap( signal ) {| | block } => obj
601 *
602 * Specifies the handling of signals. The first parameter is a signal
603 * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
604 * signal number. The characters ``SIG'' may be omitted from the
605 * signal name. The command or block specifies code to be run when the
606 * signal is raised.
607 * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
608 * will be ignored.
609 * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
610 * will be invoked.
611 * If the command is ``EXIT'', the script will be terminated by the signal.
612 * If the command is ``SYSTEM_DEFAULT'', the operating system's default
613 * handler will be invoked.
614 * Otherwise, the given command or block will be run.
615 * The special signal name ``EXIT'' or signal number zero will be
616 * invoked just prior to program termination.
617 * trap returns the previous handler for the given signal.
618 *
619 * Signal.trap(0, proc { puts "Terminating: #{$$}" })
620 * Signal.trap("CLD") { puts "Child died" }
621 * fork && Process.wait
622 *
623 * produces:
624 * Terminating: 27461
625 * Child died
626 * Terminating: 27460
627 */
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
628
9c1d230 committing experimental branch content
Laurent Sansonetti authored
629 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
630 sig_trap(VALUE rcv, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
631 {
632 struct trap_arg arg;
633
634 rb_secure(2);
635 if (argc == 0 || argc > 2) {
636 rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
637 }
638
639 arg.sig = trap_signm(argv[0]);
640 if (argc == 1) {
641 arg.cmd = rb_block_proc();
642 arg.func = sighandler;
643 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
644 else {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
645 arg.cmd = argv[1];
646 arg.func = trap_handler(&arg.cmd, arg.sig);
647 }
648
649 if (OBJ_TAINTED(arg.cmd)) {
650 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
651 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
652
9c1d230 committing experimental branch content
Laurent Sansonetti authored
653 return trap(&arg);
654 }
655
656 /*
657 * call-seq:
658 * Signal.list => a_hash
659 *
660 * Returns a list of signal names mapped to the corresponding
661 * underlying signal numbers.
662 *
663 * 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}
664 */
665 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
666 sig_list(VALUE rcv, SEL sel)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
667 {
668 VALUE h = rb_hash_new();
669 const struct signals *sigs;
670
671 for (sigs = siglist; sigs->signm; sigs++) {
672 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
673 }
674 return h;
675 }
676
677 static void
678 install_sighandler(int signum, sighandler_t handler)
679 {
680 sighandler_t old;
681
682 old = ruby_signal(signum, handler);
683 if (old != SIG_DFL) {
684 ruby_signal(signum, old);
685 }
686 }
687
688 #if defined(SIGCLD) || defined(SIGCHLD)
689 static void
690 init_sigchld(int sig)
691 {
692 sighandler_t oldfunc;
693
694 oldfunc = ruby_signal(sig, SIG_DFL);
695 if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
696 ruby_signal(sig, oldfunc);
697 } else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
698 rb_vm_set_trap_for_signal((VALUE)0, rb_safe_level(), sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
699 }
700 }
701 #endif
702
703 void
704 ruby_sig_finalize()
705 {
706 sighandler_t oldfunc;
707
708 oldfunc = ruby_signal(SIGINT, SIG_IGN);
709 if (oldfunc == sighandler) {
710 ruby_signal(SIGINT, SIG_DFL);
711 }
712 }
713
714 #ifdef RUBY_DEBUG_ENV
715 int ruby_enable_coredump = 0;
716 #endif
717
718 /*
719 * Many operating systems allow signals to be sent to running
720 * processes. Some signals have a defined effect on the process, while
721 * others may be trapped at the code level and acted upon. For
722 * example, your process may trap the USR1 signal and use it to toggle
723 * debugging, and may use TERM to initiate a controlled shutdown.
724 *
725 * pid = fork do
726 * Signal.trap("USR1") do
727 * $debug = !$debug
728 * puts "Debug now: #$debug"
729 * end
730 * Signal.trap("TERM") do
731 * puts "Terminating..."
732 * shutdown()
733 * end
734 * # . . . do some work . . .
735 * end
736 *
737 * Process.detach(pid)
738 *
739 * # Controlling program:
740 * Process.kill("USR1", pid)
741 * # ...
742 * Process.kill("USR1", pid)
743 * # ...
744 * Process.kill("TERM", pid)
745 *
746 * produces:
747 * Debug now: true
748 * Debug now: false
749 * Terminating...
750 *
751 * The list of available signal names and their interpretation is
752 * system dependent. Signal delivery semantics may also vary between
753 * systems; in particular signal delivery may not always be reliable.
754 */
755 void
756 Init_signal(void)
757 {
758 #ifndef MACOS_UNUSE_SIGNAL
759 VALUE mSignal = rb_define_module("Signal");
760
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
761 rb_objc_define_module_function(rb_mKernel, "trap", sig_trap, -1);
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
762 rb_objc_define_method(*(VALUE *)mSignal, "trap", sig_trap, -1);
763 rb_objc_define_method(*(VALUE *)mSignal, "list", sig_list, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
764
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
765 rb_objc_define_method(rb_eSignal, "initialize", esignal_init, -1);
766 rb_objc_define_method(rb_eSignal, "signo", esignal_signo, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
767 rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
768 rb_objc_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
769
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
770 /* install_sighandler(SIGINT, sighandler); */
771 /* install_sighandler(SIGHUP, sighandler); */
772 /* install_sighandler(SIGQUIT, sighandler); */
773 /* install_sighandler(SIGTERM, sighandler); */
774 /* install_sighandler(SIGALRM, sighandler); */
775 /* install_sighandler(SIGUSR1, sighandler); */
776 /* install_sighandler(SIGUSR2, sighandler); */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
777
778 #ifdef RUBY_DEBUG_ENV
779 if (!ruby_enable_coredump)
780 #endif
781 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
782 install_sighandler(SIGBUS, sigbus);
783 install_sighandler(SIGSEGV, sigsegv);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
784 }
785 install_sighandler(SIGPIPE, sigpipe);
786
787 init_sigchld(SIGCHLD);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
788 #endif /* !MACOS_UNUSE_SIGNAL */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
789 }
Something went wrong with that request. Please try again.