1 /* Signals handling. */
11 #ifdef HAVE_SYS_SIGNAL_H
12 #include <sys/signal.h>
14 #include <sys/types.h>
15 #ifdef HAVE_SYS_WAIT_H
24 #include "main/main.h"
25 #include "main/select.h"
26 #include "main/version.h"
27 #include "osdep/signals.h"
28 #include "terminal/kbd.h"
29 #include "terminal/terminal.h"
30 #include "util/error.h"
33 static void unhandle_basic_signals(struct terminal
*term
);
36 sig_terminate(struct terminal
*term
)
38 unhandle_basic_signals(term
);
39 program
.terminate
= 1;
40 program
.retval
= RET_SIGNAL
;
45 sig_intr(struct terminal
*term
)
47 unhandle_basic_signals(term
);
50 program
.terminate
= 1;
52 register_bottom_half(destroy_terminal
, term
);
57 sig_ctrl_c(struct terminal
*term
)
59 if (!is_blocked()) kbd_ctrl_c();
69 #if defined(SIGTSTP) || defined(SIGTTIN)
71 sig_tstp(struct terminal
*term
)
77 #if defined (SIGCONT) && defined(SIGTTOU)
81 /* Use _exit() rather than exit(), so that atexit
82 * functions are not called, and stdio output buffers
83 * are not flushed. Any such things must have been
84 * inherited from the parent process, which will take
85 * care of them when appropriate. */
96 sig_cont(struct terminal
*term
)
98 if (!unblock_itrm()) resize_terminal();
102 #ifdef CONFIG_BACKTRACE
104 sig_segv(struct terminal
*term
)
106 /* Get some attention. */
107 fputs("\a", stderr
); fflush(stderr
); sleep(1); fputs("\a\n", stderr
);
110 fputs( "ELinks crashed. That shouldn't happen. Please report this incident to\n"
111 "the developers. If you would like to help to debug the problem you just\n"
112 "uncovered, please keep the core you just got and send the developers\n"
113 "the output of 'bt' command entered inside of gdb (which you run as:\n"
114 "gdb elinks core). Thanks a lot for your cooperation!\n\n", stderr
);
116 /* version information */
117 fputs(full_static_version
, stderr
);
118 fputs("\n\n", stderr
);
121 dump_backtrace(stderr
, 1);
123 /* TODO: Perhaps offer launching of gdb? Or trying to continue w/
124 * program execution? --pasky */
126 /* The fastest way OUT! */
133 handle_basic_signals(struct terminal
*term
)
136 install_signal_handler(SIGHUP
, (void (*)(void *)) sig_intr
, term
, 0);
138 install_signal_handler(SIGINT
, (void (*)(void *)) sig_ctrl_c
, term
, 0);
139 install_signal_handler(SIGTERM
, (void (*)(void *)) sig_terminate
, term
, 0);
141 install_signal_handler(SIGTSTP
, (void (*)(void *)) sig_tstp
, term
, 0);
144 install_signal_handler(SIGTTIN
, (void (*)(void *)) sig_tstp
, term
, 0);
147 install_signal_handler(SIGTTOU
, (void (*)(void *)) sig_ign
, term
, 0);
150 install_signal_handler(SIGCONT
, (void (*)(void *)) sig_cont
, term
, 0);
152 #ifdef CONFIG_BACKTRACE
153 install_signal_handler(SIGSEGV
, (void (*)(void *)) sig_segv
, term
, 1);
158 unhandle_terminal_signals(struct terminal
*term
)
161 install_signal_handler(SIGHUP
, NULL
, NULL
, 0);
163 install_signal_handler(SIGINT
, NULL
, NULL
, 0);
165 install_signal_handler(SIGTSTP
, NULL
, NULL
, 0);
168 install_signal_handler(SIGTTIN
, NULL
, NULL
, 0);
171 install_signal_handler(SIGTTOU
, NULL
, NULL
, 0);
174 install_signal_handler(SIGCONT
, NULL
, NULL
, 0);
176 #ifdef CONFIG_BACKTRACE
177 install_signal_handler(SIGSEGV
, NULL
, NULL
, 0);
182 unhandle_basic_signals(struct terminal
*term
)
185 install_signal_handler(SIGHUP
, NULL
, NULL
, 0);
187 install_signal_handler(SIGINT
, NULL
, NULL
, 0);
188 install_signal_handler(SIGTERM
, NULL
, NULL
, 0);
190 install_signal_handler(SIGTSTP
, NULL
, NULL
, 0);
193 install_signal_handler(SIGTTIN
, NULL
, NULL
, 0);
196 install_signal_handler(SIGTTOU
, NULL
, NULL
, 0);
199 install_signal_handler(SIGCONT
, NULL
, NULL
, 0);
201 #ifdef CONFIG_BACKTRACE
202 install_signal_handler(SIGSEGV
, NULL
, NULL
, 0);
207 void (*handler
)(void *);
213 static struct signal_info signal_info
[NUM_SIGNALS
];
214 volatile int critical_section
= 0;
216 static void check_for_select_race(void);
218 /* TODO: In order to gain better portability, we should use signal() instead.
219 * Highest care should be given to careful watching of which signals are
220 * blocked and which aren't then, though. --pasky */
225 struct signal_info
*s
;
226 int saved_errno
= errno
;
228 if (sig
>= NUM_SIGNALS
|| sig
< 0) {
229 /* Signal handler - we have no good way how to tell this the
230 * user. She won't care anyway, tho'. */
234 s
= &signal_info
[sig
];
236 if (!s
->handler
) return;
245 check_for_select_race();
251 install_signal_handler(int sig
, void (*fn
)(void *), void *data
, int critical
)
253 #ifdef HAVE_SIGACTION
256 void (*handler
)(int) = fn
? got_signal
: SIG_IGN
;
259 /* Yes, assertm() in signal handler is totally unsafe and depends just
260 * on good luck. But hey, assert()ions are never triggered ;-). */
261 assertm(sig
>= 0 && sig
< NUM_SIGNALS
, "bad signal number: %d", sig
);
262 if_assert_failed
return;
264 #ifdef HAVE_SIGACTION
265 /* AIX has problem with empty static initializers. */
266 memset(&sa
, 0, sizeof(sa
));
269 sa
.sa_handler
= SIG_IGN
;
271 sa
.sa_handler
= got_signal
;
273 sigfillset(&sa
.sa_mask
);
274 if (!fn
) sigaction(sig
, &sa
, NULL
);
277 signal_info
[sig
].handler
= fn
;
278 signal_info
[sig
].data
= data
;
279 signal_info
[sig
].critical
= critical
;
281 #ifdef HAVE_SIGACTION
282 if (fn
) sigaction(sig
, &sa
, NULL
);
284 signal(sig
, handler
);
288 static volatile int pending_alarm
= 0;
292 alarm_handler(void *x
)
295 check_for_select_race();
300 check_for_select_race(void)
302 if (critical_section
) {
304 install_signal_handler(SIGALRM
, alarm_handler
, NULL
, 1);
314 uninstall_alarm(void)
328 while ((int) waitpid(-1, NULL
, WNOHANG
) > 0);
339 install_signal_handler(SIGCHLD
, sig_chld
, NULL
, 1);
344 clear_signal_mask_and_handlers(void)
346 memset(signal_info
, 0, sizeof(signal_info
));
354 for (i
= 0; i
< NUM_SIGNALS
; i
++) {
355 struct signal_info
*s
= &signal_info
[i
];
357 if (!s
->mask
) continue;
362 check_bottom_halves();