Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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