1
/* Signals handling. */
2
/* $Id: signals.c,v 1.19 2004/01/08 13:13:50 jonas Exp $ */
11
#ifdef HAVE_SYS_SIGNAL_H
12
#include <sys/signal.h>
14
#include <sys/types.h>
15
#ifdef HAVE_SYS_WAIT_H
25
/* This does not deserve to survive. Gotta be moved... somewhere else.
26
* 'nuff said. --pasky */
27
#include "dialogs/menu.h"
28
#include "intl/gettext/libintl.h"
29
#include "lowlevel/select.h"
30
#include "lowlevel/signals.h"
31
#include "modules/version.h"
32
#include "terminal/kbd.c"
33
#include "util/error.h"
36
static void unhandle_basic_signals(struct terminal *term);
39
sig_terminate(struct terminal *t)
41
unhandle_basic_signals(t);
47
sig_intr(struct terminal *t)
49
unhandle_basic_signals(t);
54
register_bottom_half((void (*)(void *))destroy_terminal, t);
58
sig_ctrl_c(struct terminal *t)
60
if (!is_blocked()) kbd_ctrl_c();
69
sig_tstp(struct terminal *t)
75
#if defined (SIGCONT) && defined(SIGTTOU)
87
sig_cont(struct terminal *t)
89
if (!unblock_itrm(0)) resize_terminal();
92
#ifdef CONFIG_BACKTRACE
94
sig_segv(struct terminal *t)
96
/* Get some attention. */
97
fputs("\a", stderr); fflush(stderr); sleep(1); fputs("\a\n", stderr);
100
fputs( "ELinks crashed. That shouldn't happen. Please report this incident to\n"
101
"developers. Preferrably please include information about what probably\n"
102
"triggered this and the listout below. Note that it does NOT supercede the gdb\n"
103
"output, which is way more useful for developers. If you would like to help to\n"
104
"debug the problem you just uncovered, please keep the core you just got and\n"
105
"send the developers output of 'bt' command entered inside of gdb (which you run\n"
106
"as gdb elinks core). Thanks a lot for your cooperation!\n\n", stderr);
108
/* version information */
109
fputs(full_static_version, stderr);
110
fputs("\n\n", stderr);
113
dump_backtrace(stderr, 1);
115
/* TODO: Perhaps offer launching of gdb? Or trying to continue w/
116
* program execution? --pasky */
118
/* The fastest way OUT! */
125
handle_basic_signals(struct terminal *term)
127
install_signal_handler(SIGHUP, (void (*)(void *))sig_intr, term, 0);
128
install_signal_handler(SIGINT, (void (*)(void *))sig_ctrl_c, term, 0);
129
install_signal_handler(SIGTERM, (void (*)(void *))sig_terminate, term, 0);
131
install_signal_handler(SIGTSTP, (void (*)(void *))sig_tstp, term, 0);
134
install_signal_handler(SIGTTIN, (void (*)(void *))sig_tstp, term, 0);
137
install_signal_handler(SIGTTOU, (void (*)(void *))sig_ign, term, 0);
140
install_signal_handler(SIGCONT, (void (*)(void *))sig_cont, term, 0);
142
#ifdef CONFIG_BACKTRACE
143
install_signal_handler(SIGSEGV, (void (*)(void *))sig_segv, term, 1);
148
unhandle_terminal_signals(struct terminal *term)
150
install_signal_handler(SIGHUP, NULL, NULL, 0);
151
install_signal_handler(SIGINT, NULL, NULL, 0);
153
install_signal_handler(SIGTSTP, NULL, NULL, 0);
156
install_signal_handler(SIGTTIN, NULL, NULL, 0);
159
install_signal_handler(SIGTTOU, NULL, NULL, 0);
162
install_signal_handler(SIGCONT, NULL, NULL, 0);
164
#ifdef CONFIG_BACKTRACE
165
install_signal_handler(SIGSEGV, NULL, NULL, 0);
170
unhandle_basic_signals(struct terminal *term)
172
install_signal_handler(SIGHUP, NULL, NULL, 0);
173
install_signal_handler(SIGINT, NULL, NULL, 0);
174
install_signal_handler(SIGTERM, NULL, NULL, 0);
176
install_signal_handler(SIGTSTP, NULL, NULL, 0);
179
install_signal_handler(SIGTTIN, NULL, NULL, 0);
182
install_signal_handler(SIGTTOU, NULL, NULL, 0);
185
install_signal_handler(SIGCONT, NULL, NULL, 0);
187
#ifdef CONFIG_BACKTRACE
188
install_signal_handler(SIGSEGV, NULL, NULL, 0);
193
void (*handler)(void *);
199
static struct signal_info signal_info[NUM_SIGNALS];
200
volatile int critical_section = 0;
202
static void check_for_select_race(void);
204
/* TODO: In order to gain better portability, we should use signal() instead.
205
* Highest care should be given to careful watching of which signals are
206
* blocked and which aren't then, though. --pasky */
211
struct signal_info *s;
213
if (sig >= NUM_SIGNALS || sig < 0) {
214
/* Signal handler - we have no good way how to tell this the
215
* user. She won't care anyway, tho'. */
219
s = &signal_info[sig];
221
if (!s->handler) return;
229
check_for_select_race();
233
install_signal_handler(int sig, void (*fn)(void *), void *data, int critical)
235
struct sigaction sa = {};
237
/* Yes, assertm() in signal handler is totally unsafe and depends just
238
* on good luck. But hey, assert()ions are never triggered ;-). */
239
assertm(sig >= 0 && sig < NUM_SIGNALS, "bad signal number: %d", sig);
240
if_assert_failed return;
243
sa.sa_handler = SIG_IGN;
245
sa.sa_handler = got_signal;
247
sigfillset(&sa.sa_mask);
248
if (!fn) sigaction(sig, &sa, NULL);
249
signal_info[sig].handler = fn;
250
signal_info[sig].data = data;
251
signal_info[sig].critical = critical;
252
if (fn) sigaction(sig, &sa, NULL);
255
static volatile int pending_alarm = 0;
258
alarm_handler(void *x)
261
check_for_select_race();
265
check_for_select_race(void)
267
if (critical_section) {
269
install_signal_handler(SIGALRM, alarm_handler, NULL, 1);
279
uninstall_alarm(void)
292
while ((int) waitpid(-1, NULL, WNOHANG) > 0);
301
install_signal_handler(SIGCHLD, sigchld, NULL, 1);
305
clear_signal_mask_and_handlers(void)
307
memset(signal_info, 0, sizeof(signal_info));
315
for (i = 0; i < NUM_SIGNALS; i++) {
316
struct signal_info *s = &signal_info[i];
318
if (!s->mask) continue;
323
check_bottom_halves();