1 /* Signals handling. */
2 /* $Id: signals.c,v 1.35 2005/07/04 01:37:36 miciah Exp $ */
12 #ifdef HAVE_SYS_SIGNAL_H
13 #include <sys/signal.h>
15 #include <sys/types.h>
16 #ifdef HAVE_SYS_WAIT_H
25 #include "main/main.h"
26 #include "main/select.h"
27 #include "main/version.h"
28 #include "osdep/signals.h"
29 #include "terminal/kbd.h"
30 #include "terminal/terminal.h"
31 #include "util/error.h"
34 static void unhandle_basic_signals(struct terminal
*term
);
37 sig_terminate(struct terminal
*term
)
39 unhandle_basic_signals(term
);
40 program
.terminate
= 1;
41 program
.retval
= RET_SIGNAL
;
46 sig_intr(struct terminal
*term
)
48 unhandle_basic_signals(term
);
51 program
.terminate
= 1;
53 register_bottom_half(destroy_terminal
, term
);
58 sig_ctrl_c(struct terminal
*term
)
60 if (!is_blocked()) kbd_ctrl_c();
70 #if defined(SIGTSTP) || defined(SIGTTIN)
72 sig_tstp(struct terminal
*term
)
78 #if defined (SIGCONT) && defined(SIGTTOU)
92 sig_cont(struct terminal
*term
)
94 if (!unblock_itrm(0)) resize_terminal();
98 #ifdef CONFIG_BACKTRACE
100 sig_segv(struct terminal
*term
)
102 /* Get some attention. */
103 fputs("\a", stderr
); fflush(stderr
); sleep(1); fputs("\a\n", stderr
);
106 fputs( "ELinks crashed. That shouldn't happen. Please report this incident to\n"
107 "the developers. If you would like to help to debug the problem you just\n"
108 "uncovered, please keep the core you just got and send the developers\n"
109 "the output of 'bt' command entered inside of gdb (which you run as:\n"
110 "gdb elinks core). Thanks a lot for your cooperation!\n\n", stderr
);
112 /* version information */
113 fputs(full_static_version
, stderr
);
114 fputs("\n\n", stderr
);
117 dump_backtrace(stderr
, 1);
119 /* TODO: Perhaps offer launching of gdb? Or trying to continue w/
120 * program execution? --pasky */
122 /* The fastest way OUT! */
129 handle_basic_signals(struct terminal
*term
)
132 install_signal_handler(SIGHUP
, (void (*)(void *)) sig_intr
, term
, 0);
134 install_signal_handler(SIGINT
, (void (*)(void *)) sig_ctrl_c
, term
, 0);
135 install_signal_handler(SIGTERM
, (void (*)(void *)) sig_terminate
, term
, 0);
137 install_signal_handler(SIGTSTP
, (void (*)(void *)) sig_tstp
, term
, 0);
140 install_signal_handler(SIGTTIN
, (void (*)(void *)) sig_tstp
, term
, 0);
143 install_signal_handler(SIGTTOU
, (void (*)(void *)) sig_ign
, term
, 0);
146 install_signal_handler(SIGCONT
, (void (*)(void *)) sig_cont
, term
, 0);
148 #ifdef CONFIG_BACKTRACE
149 install_signal_handler(SIGSEGV
, (void (*)(void *)) sig_segv
, term
, 1);
154 unhandle_terminal_signals(struct terminal
*term
)
157 install_signal_handler(SIGHUP
, NULL
, NULL
, 0);
159 install_signal_handler(SIGINT
, NULL
, NULL
, 0);
161 install_signal_handler(SIGTSTP
, NULL
, NULL
, 0);
164 install_signal_handler(SIGTTIN
, NULL
, NULL
, 0);
167 install_signal_handler(SIGTTOU
, NULL
, NULL
, 0);
170 install_signal_handler(SIGCONT
, NULL
, NULL
, 0);
172 #ifdef CONFIG_BACKTRACE
173 install_signal_handler(SIGSEGV
, NULL
, NULL
, 0);
178 unhandle_basic_signals(struct terminal
*term
)
181 install_signal_handler(SIGHUP
, NULL
, NULL
, 0);
183 install_signal_handler(SIGINT
, NULL
, NULL
, 0);
184 install_signal_handler(SIGTERM
, NULL
, NULL
, 0);
186 install_signal_handler(SIGTSTP
, NULL
, NULL
, 0);
189 install_signal_handler(SIGTTIN
, NULL
, NULL
, 0);
192 install_signal_handler(SIGTTOU
, NULL
, NULL
, 0);
195 install_signal_handler(SIGCONT
, NULL
, NULL
, 0);
197 #ifdef CONFIG_BACKTRACE
198 install_signal_handler(SIGSEGV
, NULL
, NULL
, 0);
203 void (*handler
)(void *);
209 static struct signal_info signal_info
[NUM_SIGNALS
];
210 volatile int critical_section
= 0;
212 static void check_for_select_race(void);
214 /* TODO: In order to gain better portability, we should use signal() instead.
215 * Highest care should be given to careful watching of which signals are
216 * blocked and which aren't then, though. --pasky */
221 struct signal_info
*s
;
222 int saved_errno
= errno
;
224 if (sig
>= NUM_SIGNALS
|| sig
< 0) {
225 /* Signal handler - we have no good way how to tell this the
226 * user. She won't care anyway, tho'. */
230 s
= &signal_info
[sig
];
232 if (!s
->handler
) return;
241 check_for_select_race();
247 install_signal_handler(int sig
, void (*fn
)(void *), void *data
, int critical
)
249 #ifdef HAVE_SIGACTION
252 void (*handler
)(int) = fn
? got_signal
: SIG_IGN
;
255 /* Yes, assertm() in signal handler is totally unsafe and depends just
256 * on good luck. But hey, assert()ions are never triggered ;-). */
257 assertm(sig
>= 0 && sig
< NUM_SIGNALS
, "bad signal number: %d", sig
);
258 if_assert_failed
return;
260 #ifdef HAVE_SIGACTION
261 /* AIX has problem with empty static initializers. */
262 memset(&sa
, 0, sizeof(sa
));
265 sa
.sa_handler
= SIG_IGN
;
267 sa
.sa_handler
= got_signal
;
269 sigfillset(&sa
.sa_mask
);
270 if (!fn
) sigaction(sig
, &sa
, NULL
);
273 signal_info
[sig
].handler
= fn
;
274 signal_info
[sig
].data
= data
;
275 signal_info
[sig
].critical
= critical
;
277 #ifdef HAVE_SIGACTION
278 if (fn
) sigaction(sig
, &sa
, NULL
);
280 signal(sig
, handler
);
284 static volatile int pending_alarm
= 0;
288 alarm_handler(void *x
)
291 check_for_select_race();
296 check_for_select_race(void)
298 if (critical_section
) {
300 install_signal_handler(SIGALRM
, alarm_handler
, NULL
, 1);
310 uninstall_alarm(void)
324 while ((int) waitpid(-1, NULL
, WNOHANG
) > 0);
335 install_signal_handler(SIGCHLD
, sig_chld
, NULL
, 1);
340 clear_signal_mask_and_handlers(void)
342 memset(signal_info
, 0, sizeof(signal_info
));
350 for (i
= 0; i
< NUM_SIGNALS
; i
++) {
351 struct signal_info
*s
= &signal_info
[i
];
353 if (!s
->mask
) continue;
358 check_bottom_halves();