Skip to content

HTTPS clone URL

Subversion checkout URL

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