]> git.ipfire.org Git - thirdparty/bash.git/blame - sig.c
Bash-5.0 patch 17: better fix for reaping process substitution file descriptors
[thirdparty/bash.git] / sig.c
CommitLineData
ccc6cda3
JA
1/* sig.c - interface for shell signal handlers and signal initialization. */
2
d233b485 3/* Copyright (C) 1994-2018 Free Software Foundation, Inc.
ccc6cda3
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
3185942a
JA
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
ccc6cda3 11
3185942a
JA
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
ccc6cda3 16
3185942a
JA
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
ccc6cda3
JA
20
21#include "config.h"
22
23#include "bashtypes.h"
24
25#if defined (HAVE_UNISTD_H)
cce855bc
JA
26# ifdef _MINIX
27# include <sys/types.h>
28# endif
ccc6cda3
JA
29# include <unistd.h>
30#endif
31
32#include <stdio.h>
33#include <signal.h>
34
b80f6443
JA
35#include "bashintl.h"
36
ccc6cda3 37#include "shell.h"
d233b485 38#include "execute_cmd.h"
ccc6cda3
JA
39#if defined (JOB_CONTROL)
40#include "jobs.h"
41#endif /* JOB_CONTROL */
42#include "siglist.h"
43#include "sig.h"
44#include "trap.h"
45
46#include "builtins/common.h"
ac50fbac 47#include "builtins/builtext.h"
ccc6cda3
JA
48
49#if defined (READLINE)
50# include "bashline.h"
d5d00961 51# include <readline/readline.h>
ccc6cda3
JA
52#endif
53
54#if defined (HISTORY)
55# include "bashhist.h"
56#endif
57
495aee44 58extern void initialize_siglist ();
ccc6cda3 59
a0c0a00f
CR
60#if !defined (JOB_CONTROL)
61extern void initialize_job_signals __P((void));
62#endif
63
ccc6cda3 64/* Non-zero after SIGINT. */
ac50fbac 65volatile sig_atomic_t interrupt_state = 0;
ccc6cda3 66
95732b49 67/* Non-zero after SIGWINCH */
ac50fbac
CR
68volatile sig_atomic_t sigwinch_received = 0;
69
70/* Non-zero after SIGTERM */
71volatile sig_atomic_t sigterm_received = 0;
95732b49 72
0628567a 73/* Set to the value of any terminating signal received. */
ac50fbac 74volatile sig_atomic_t terminating_signal = 0;
0628567a 75
ccc6cda3
JA
76/* The environment at the top-level R-E loop. We use this in
77 the case of error return. */
78procenv_t top_level;
79
80#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
81/* The signal masks that this shell runs with. */
82sigset_t top_level_mask;
83#endif /* JOB_CONTROL */
84
85/* When non-zero, we throw_to_top_level (). */
86int interrupt_immediately = 0;
87
0628567a
JA
88/* When non-zero, we call the terminating signal handler immediately. */
89int terminate_immediately = 0;
90
95732b49
JA
91#if defined (SIGWINCH)
92static SigHandler *old_winch = (SigHandler *)SIG_DFL;
93#endif
94
f73dda09 95static void initialize_shell_signals __P((void));
ccc6cda3
JA
96
97void
7117c2d2
JA
98initialize_signals (reinit)
99 int reinit;
ccc6cda3 100{
d166f048 101 initialize_shell_signals ();
ccc6cda3 102 initialize_job_signals ();
e8ce775d 103#if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
7117c2d2
JA
104 if (reinit == 0)
105 initialize_siglist ();
e8ce775d 106#endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
ccc6cda3
JA
107}
108
ccc6cda3
JA
109/* A structure describing a signal that terminates the shell if not
110 caught. The orig_handler member is present so children can reset
111 these signals back to their original handlers. */
112struct termsig {
113 int signum;
114 SigHandler *orig_handler;
95732b49 115 int orig_flags;
d233b485 116 int core_dump;
ccc6cda3
JA
117};
118
119#define NULL_HANDLER (SigHandler *)SIG_DFL
120
121/* The list of signals that would terminate the shell if not caught.
122 We catch them, but just so that we can write the history file,
123 and so forth. */
124static struct termsig terminating_signals[] = {
125#ifdef SIGHUP
95732b49 126{ SIGHUP, NULL_HANDLER, 0 },
ccc6cda3
JA
127#endif
128
129#ifdef SIGINT
95732b49 130{ SIGINT, NULL_HANDLER, 0 },
ccc6cda3
JA
131#endif
132
133#ifdef SIGILL
d233b485 134{ SIGILL, NULL_HANDLER, 0, 1},
ccc6cda3
JA
135#endif
136
137#ifdef SIGTRAP
d233b485 138{ SIGTRAP, NULL_HANDLER, 0, 1 },
ccc6cda3
JA
139#endif
140
141#ifdef SIGIOT
d233b485 142{ SIGIOT, NULL_HANDLER, 0, 1 },
ccc6cda3
JA
143#endif
144
145#ifdef SIGDANGER
95732b49 146{ SIGDANGER, NULL_HANDLER, 0 },
ccc6cda3
JA
147#endif
148
149#ifdef SIGEMT
95732b49 150{ SIGEMT, NULL_HANDLER, 0 },
ccc6cda3
JA
151#endif
152
153#ifdef SIGFPE
d233b485 154{ SIGFPE, NULL_HANDLER, 0, 1 },
ccc6cda3
JA
155#endif
156
157#ifdef SIGBUS
d233b485 158{ SIGBUS, NULL_HANDLER, 0, 1 },
ccc6cda3
JA
159#endif
160
161#ifdef SIGSEGV
d233b485 162{ SIGSEGV, NULL_HANDLER, 0, 1 },
ccc6cda3
JA
163#endif
164
165#ifdef SIGSYS
d233b485 166{ SIGSYS, NULL_HANDLER, 0, 1 },
ccc6cda3
JA
167#endif
168
169#ifdef SIGPIPE
95732b49 170{ SIGPIPE, NULL_HANDLER, 0 },
ccc6cda3
JA
171#endif
172
173#ifdef SIGALRM
95732b49 174{ SIGALRM, NULL_HANDLER, 0 },
ccc6cda3
JA
175#endif
176
177#ifdef SIGTERM
95732b49 178{ SIGTERM, NULL_HANDLER, 0 },
ccc6cda3
JA
179#endif
180
d233b485
CR
181/* These don't generate core dumps on anything but Linux, but we're doing
182 this just for Linux anyway. */
ccc6cda3 183#ifdef SIGXCPU
d233b485 184{ SIGXCPU, NULL_HANDLER, 0, 1 },
ccc6cda3
JA
185#endif
186
187#ifdef SIGXFSZ
d233b485 188{ SIGXFSZ, NULL_HANDLER, 0, 1 },
ccc6cda3
JA
189#endif
190
191#ifdef SIGVTALRM
95732b49 192{ SIGVTALRM, NULL_HANDLER, 0 },
ccc6cda3
JA
193#endif
194
bb70624e 195#if 0
ccc6cda3 196#ifdef SIGPROF
95732b49 197{ SIGPROF, NULL_HANDLER, 0 },
ccc6cda3 198#endif
bb70624e 199#endif
ccc6cda3
JA
200
201#ifdef SIGLOST
95732b49 202{ SIGLOST, NULL_HANDLER, 0 },
ccc6cda3
JA
203#endif
204
205#ifdef SIGUSR1
95732b49 206{ SIGUSR1, NULL_HANDLER, 0 },
ccc6cda3
JA
207#endif
208
209#ifdef SIGUSR2
95732b49 210{ SIGUSR2, NULL_HANDLER, 0 },
ccc6cda3
JA
211#endif
212};
213
214#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
215
216#define XSIG(x) (terminating_signals[x].signum)
217#define XHANDLER(x) (terminating_signals[x].orig_handler)
95732b49 218#define XSAFLAGS(x) (terminating_signals[x].orig_flags)
d233b485 219#define XCOREDUMP(x) (terminating_signals[x].core_dump)
ccc6cda3 220
d166f048
JA
221static int termsigs_initialized = 0;
222
ccc6cda3 223/* Initialize signals that will terminate the shell to do some
d166f048 224 unwind protection. For non-interactive shells, we only call
495aee44
CR
225 this when a trap is defined for EXIT (0) or when trap is run
226 to display signal dispositions. */
d166f048 227void
ccc6cda3
JA
228initialize_terminating_signals ()
229{
230 register int i;
d166f048
JA
231#if defined (HAVE_POSIX_SIGNALS)
232 struct sigaction act, oact;
233#endif
234
235 if (termsigs_initialized)
236 return;
ccc6cda3
JA
237
238 /* The following code is to avoid an expensive call to
239 set_signal_handler () for each terminating_signals. Fortunately,
240 this is possible in Posix. Unfortunately, we have to call signal ()
241 on non-Posix systems for each signal in terminating_signals. */
242#if defined (HAVE_POSIX_SIGNALS)
0628567a 243 act.sa_handler = termsig_sighandler;
ccc6cda3
JA
244 act.sa_flags = 0;
245 sigemptyset (&act.sa_mask);
246 sigemptyset (&oact.sa_mask);
247 for (i = 0; i < TERMSIGS_LENGTH; i++)
248 sigaddset (&act.sa_mask, XSIG (i));
249 for (i = 0; i < TERMSIGS_LENGTH; i++)
250 {
7117c2d2
JA
251 /* If we've already trapped it, don't do anything. */
252 if (signal_is_trapped (XSIG (i)))
253 continue;
254
ccc6cda3 255 sigaction (XSIG (i), &act, &oact);
d166f048 256 XHANDLER(i) = oact.sa_handler;
95732b49 257 XSAFLAGS(i) = oact.sa_flags;
ccc6cda3
JA
258 /* Don't do anything with signals that are ignored at shell entry
259 if the shell is not interactive. */
495aee44
CR
260 /* XXX - should we do this for interactive shells, too? */
261 if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
28ef6c31 262 {
ccc6cda3 263 sigaction (XSIG (i), &oact, &act);
ac50fbac 264 set_signal_hard_ignored (XSIG (i));
28ef6c31 265 }
cce855bc 266#if defined (SIGPROF) && !defined (_MINIX)
d166f048 267 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
28ef6c31 268 sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
cce855bc 269#endif /* SIGPROF && !_MINIX */
ccc6cda3 270 }
ccc6cda3
JA
271#else /* !HAVE_POSIX_SIGNALS */
272
273 for (i = 0; i < TERMSIGS_LENGTH; i++)
274 {
7117c2d2
JA
275 /* If we've already trapped it, don't do anything. */
276 if (signal_is_trapped (XSIG (i)))
277 continue;
278
0628567a 279 XHANDLER(i) = signal (XSIG (i), termsig_sighandler);
95732b49 280 XSAFLAGS(i) = 0;
ccc6cda3
JA
281 /* Don't do anything with signals that are ignored at shell entry
282 if the shell is not interactive. */
495aee44
CR
283 /* XXX - should we do this for interactive shells, too? */
284 if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
ccc6cda3 285 {
28ef6c31 286 signal (XSIG (i), SIG_IGN);
ac50fbac 287 set_signal_hard_ignored (XSIG (i));
ccc6cda3 288 }
cce855bc 289#ifdef SIGPROF
d166f048 290 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
28ef6c31 291 signal (XSIG (i), XHANDLER (i));
cce855bc 292#endif
ccc6cda3
JA
293 }
294
295#endif /* !HAVE_POSIX_SIGNALS */
296
d166f048
JA
297 termsigs_initialized = 1;
298}
299
300static void
301initialize_shell_signals ()
302{
303 if (interactive)
304 initialize_terminating_signals ();
305
ccc6cda3
JA
306#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
307 /* All shells use the signal mask they inherit, and pass it along
308 to child processes. Children will never block SIGCHLD, though. */
309 sigemptyset (&top_level_mask);
310 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
bb70624e 311# if defined (SIGCHLD)
ccc6cda3 312 sigdelset (&top_level_mask, SIGCHLD);
bb70624e 313# endif
ccc6cda3
JA
314#endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
315
316 /* And, some signals that are specifically ignored by the shell. */
317 set_signal_handler (SIGQUIT, SIG_IGN);
318
319 if (interactive)
320 {
321 set_signal_handler (SIGINT, sigint_sighandler);
ac50fbac
CR
322 get_original_signal (SIGTERM);
323 if (signal_is_hard_ignored (SIGTERM) == 0)
324 set_signal_handler (SIGTERM, sigterm_sighandler);
95732b49 325 set_sigwinch_handler ();
ccc6cda3
JA
326 }
327}
328
329void
330reset_terminating_signals ()
331{
332 register int i;
ccc6cda3
JA
333#if defined (HAVE_POSIX_SIGNALS)
334 struct sigaction act;
d166f048 335#endif
ccc6cda3 336
d166f048
JA
337 if (termsigs_initialized == 0)
338 return;
339
340#if defined (HAVE_POSIX_SIGNALS)
ccc6cda3
JA
341 act.sa_flags = 0;
342 sigemptyset (&act.sa_mask);
343 for (i = 0; i < TERMSIGS_LENGTH; i++)
344 {
345 /* Skip a signal if it's trapped or handled specially, because the
346 trap code will restore the correct value. */
347 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
348 continue;
349
350 act.sa_handler = XHANDLER (i);
95732b49 351 act.sa_flags = XSAFLAGS (i);
ccc6cda3
JA
352 sigaction (XSIG (i), &act, (struct sigaction *) NULL);
353 }
354#else /* !HAVE_POSIX_SIGNALS */
355 for (i = 0; i < TERMSIGS_LENGTH; i++)
356 {
357 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
358 continue;
359
360 signal (XSIG (i), XHANDLER (i));
361 }
362#endif /* !HAVE_POSIX_SIGNALS */
ac50fbac
CR
363
364 termsigs_initialized = 0;
ccc6cda3 365}
ccc6cda3
JA
366#undef XHANDLER
367
f1be666c
JA
368/* Run some of the cleanups that should be performed when we run
369 jump_to_top_level from a builtin command context. XXX - might want to
370 also call reset_parser here. */
371void
372top_level_cleanup ()
373{
374 /* Clean up string parser environment. */
375 while (parse_and_execute_level)
d233b485 376 parse_and_execute_cleanup (-1);
f1be666c
JA
377
378#if defined (PROCESS_SUBSTITUTION)
379 unlink_fifo_list ();
380#endif /* PROCESS_SUBSTITUTION */
381
382 run_unwind_protects ();
495aee44 383 loop_level = continuing = breaking = funcnest = 0;
a0c0a00f 384 executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
f1be666c
JA
385}
386
ccc6cda3
JA
387/* What to do when we've been interrupted, and it is safe to handle it. */
388void
389throw_to_top_level ()
390{
391 int print_newline = 0;
392
393 if (interrupt_state)
394 {
ac50fbac
CR
395 if (last_command_exit_value < 128)
396 last_command_exit_value = 128 + SIGINT;
ccc6cda3
JA
397 print_newline = 1;
398 DELINTERRUPT;
399 }
400
401 if (interrupt_state)
402 return;
403
b80f6443
JA
404 last_command_exit_signal = (last_command_exit_value > 128) ?
405 (last_command_exit_value - 128) : 0;
ccc6cda3
JA
406 last_command_exit_value |= 128;
407
a0c0a00f
CR
408 /* Run any traps set on SIGINT, mostly for interactive shells */
409 if (signal_is_trapped (SIGINT))
410 run_interrupt_trap (1);
ccc6cda3 411
3185942a 412 /* Clean up string parser environment. */
ccc6cda3 413 while (parse_and_execute_level)
d233b485 414 parse_and_execute_cleanup (-1);
ccc6cda3 415
a0c0a00f
CR
416 if (running_trap > 0)
417 run_trap_cleanup (running_trap - 1);
418
ccc6cda3 419#if defined (JOB_CONTROL)
28ef6c31 420 give_terminal_to (shell_pgrp, 0);
ccc6cda3
JA
421#endif /* JOB_CONTROL */
422
423#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
ac50fbac
CR
424 /* This needs to stay because jobs.c:make_child() uses it without resetting
425 the signal mask. */
ccc6cda3
JA
426 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
427#endif
428
429 reset_parser ();
430
431#if defined (READLINE)
432 if (interactive)
3185942a 433 bashline_reset ();
ccc6cda3
JA
434#endif /* READLINE */
435
436#if defined (PROCESS_SUBSTITUTION)
437 unlink_fifo_list ();
438#endif /* PROCESS_SUBSTITUTION */
439
440 run_unwind_protects ();
495aee44 441 loop_level = continuing = breaking = funcnest = 0;
a0c0a00f 442 executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
ccc6cda3
JA
443
444 if (interactive && print_newline)
445 {
446 fflush (stdout);
447 fprintf (stderr, "\n");
448 fflush (stderr);
449 }
450
451 /* An interrupted `wait' command in a script does not exit the script. */
452 if (interactive || (interactive_shell && !shell_initialized) ||
453 (print_newline && signal_is_trapped (SIGINT)))
454 jump_to_top_level (DISCARD);
455 else
456 jump_to_top_level (EXITPROG);
457}
458
459/* This is just here to isolate the longjmp calls. */
460void
461jump_to_top_level (value)
462 int value;
463{
a0c0a00f 464 sh_longjmp (top_level, value);
ccc6cda3
JA
465}
466
467sighandler
0628567a 468termsig_sighandler (sig)
ccc6cda3
JA
469 int sig;
470{
89a92869
CR
471 /* If we get called twice with the same signal before handling it,
472 terminate right away. */
473 if (
474#ifdef SIGHUP
475 sig != SIGHUP &&
476#endif
477#ifdef SIGINT
478 sig != SIGINT &&
479#endif
480#ifdef SIGDANGER
481 sig != SIGDANGER &&
482#endif
483#ifdef SIGPIPE
484 sig != SIGPIPE &&
485#endif
486#ifdef SIGALRM
487 sig != SIGALRM &&
488#endif
489#ifdef SIGTERM
490 sig != SIGTERM &&
491#endif
492#ifdef SIGXCPU
493 sig != SIGXCPU &&
494#endif
495#ifdef SIGXFSZ
496 sig != SIGXFSZ &&
497#endif
498#ifdef SIGVTALRM
499 sig != SIGVTALRM &&
500#endif
501#ifdef SIGLOST
502 sig != SIGLOST &&
503#endif
504#ifdef SIGUSR1
505 sig != SIGUSR1 &&
506#endif
507#ifdef SIGUSR2
508 sig != SIGUSR2 &&
509#endif
510 sig == terminating_signal)
511 terminate_immediately = 1;
512
0628567a
JA
513 terminating_signal = sig;
514
3185942a 515 /* XXX - should this also trigger when interrupt_immediately is set? */
0628567a
JA
516 if (terminate_immediately)
517 {
495aee44
CR
518#if defined (HISTORY)
519 /* XXX - will inhibit history file being written */
d5d00961
CR
520# if defined (READLINE)
521 if (interactive_shell == 0 || interactive == 0 || (sig != SIGHUP && sig != SIGTERM) || no_line_editing || (RL_ISSTATE (RL_STATE_READCMD) == 0))
522# endif
523 history_lines_this_session = 0;
495aee44 524#endif
0628567a
JA
525 terminate_immediately = 0;
526 termsig_handler (sig);
527 }
528
ac50fbac
CR
529#if defined (READLINE)
530 /* Set the event hook so readline will call it after the signal handlers
531 finish executing, so if this interrupted character input we can get
84c617ec
CR
532 quick response. If readline is active or has modified the terminal we
533 need to set this no matter what the signal is, though the check for
534 RL_STATE_TERMPREPPED is possibly redundant. */
535 if (RL_ISSTATE (RL_STATE_SIGHANDLER) || RL_ISSTATE (RL_STATE_TERMPREPPED))
ac50fbac
CR
536 bashline_set_event_hook ();
537#endif
538
0628567a
JA
539 SIGRETURN (0);
540}
541
542void
543termsig_handler (sig)
544 int sig;
545{
546 static int handling_termsig = 0;
d233b485
CR
547 int i, core;
548 sigset_t mask;
0628567a
JA
549
550 /* Simple semaphore to keep this function from being executed multiple
551 times. Since we no longer are running as a signal handler, we don't
552 block multiple occurrences of the terminating signals while running. */
553 if (handling_termsig)
554 return;
555 handling_termsig = 1;
556 terminating_signal = 0; /* keep macro from re-testing true. */
557
95732b49 558 /* I don't believe this condition ever tests true. */
ccc6cda3 559 if (sig == SIGINT && signal_is_trapped (SIGINT))
a0c0a00f 560 run_interrupt_trap (0);
ccc6cda3
JA
561
562#if defined (HISTORY)
ac50fbac
CR
563 /* If we don't do something like this, the history will not be saved when
564 an interactive shell is running in a terminal window that gets closed
565 with the `close' button. We can't test for RL_STATE_READCMD because
566 readline no longer handles SIGTERM synchronously. */
567 if (interactive_shell && interactive && (sig == SIGHUP || sig == SIGTERM) && remember_on_history)
ccc6cda3
JA
568 maybe_save_shell_history ();
569#endif /* HISTORY */
570
a0c0a00f
CR
571 if (this_shell_builtin == read_builtin)
572 read_tty_cleanup ();
573
ccc6cda3 574#if defined (JOB_CONTROL)
0001803f 575 if (sig == SIGHUP && (interactive || (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB))))
ccc6cda3 576 hangup_all_jobs ();
d233b485 577
76bb456d
CR
578 if ((subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB)) == 0)
579 end_job_control ();
ccc6cda3
JA
580#endif /* JOB_CONTROL */
581
582#if defined (PROCESS_SUBSTITUTION)
583 unlink_fifo_list ();
584#endif /* PROCESS_SUBSTITUTION */
585
3185942a 586 /* Reset execution context */
495aee44 587 loop_level = continuing = breaking = funcnest = 0;
a0c0a00f 588 executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
3185942a 589
ac50fbac 590 run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
d233b485
CR
591
592 /* We don't change the set of blocked signals. If a user starts the shell
593 with a terminating signal blocked, we won't get here (and if by some
594 magic chance we do, we'll exit below). */
ccc6cda3 595 set_signal_handler (sig, SIG_DFL);
d233b485 596
ccc6cda3 597 kill (getpid (), sig);
d233b485
CR
598
599 if (dollar_dollar_pid != 1)
600 exit (128+sig); /* just in case the kill fails? */
601
602 /* We get here only under extraordinary circumstances. */
603
604 /* We are PID 1, and the kill above failed to kill the process. We assume
605 this means that we are running as an init process in a pid namespace
606 on Linux. In this case, we can't send ourselves a fatal signal, so we
607 determine whether or not we should have generated a core dump with the
608 kill call and attempt to trick the kernel into generating one if
609 necessary. */
610 sigprocmask (SIG_SETMASK, (sigset_t *)NULL, &mask);
611 for (i = core = 0; i < TERMSIGS_LENGTH; i++)
612 {
613 set_signal_handler (XSIG (i), SIG_DFL);
614 sigdelset (&mask, XSIG (i));
615 if (sig == XSIG (i))
616 core = XCOREDUMP (i);
617 }
618 sigprocmask (SIG_SETMASK, &mask, (sigset_t *)NULL);
619
620 if (core)
621 *((volatile unsigned long *) NULL) = 0xdead0000 + sig; /* SIGSEGV */
622
623 exit (128+sig);
ccc6cda3 624}
d233b485 625#undef XSIG
ccc6cda3
JA
626
627/* What we really do when SIGINT occurs. */
628sighandler
629sigint_sighandler (sig)
630 int sig;
631{
632#if defined (MUST_REINSTALL_SIGHANDLERS)
633 signal (sig, sigint_sighandler);
634#endif
635
636 /* interrupt_state needs to be set for the stack of interrupts to work
637 right. Should it be set unconditionally? */
638 if (interrupt_state == 0)
639 ADDINTERRUPT;
640
ac50fbac 641 /* We will get here in interactive shells with job control active; allow
a0c0a00f
CR
642 an interactive wait to be interrupted. wait_intr_flag is only set during
643 the execution of the wait builtin and when wait_intr_buf is valid. */
644 if (wait_intr_flag)
ac50fbac
CR
645 {
646 last_command_exit_value = 128 + sig;
647 wait_signal_received = sig;
648 SIGRETURN (0);
649 }
650
ccc6cda3
JA
651 if (interrupt_immediately)
652 {
653 interrupt_immediately = 0;
0001803f 654 last_command_exit_value = 128 + sig;
ccc6cda3
JA
655 throw_to_top_level ();
656 }
ac50fbac
CR
657#if defined (READLINE)
658 /* Set the event hook so readline will call it after the signal handlers
659 finish executing, so if this interrupted character input we can get
660 quick response. */
661 else if (RL_ISSTATE (RL_STATE_SIGHANDLER))
662 bashline_set_event_hook ();
663#endif
ccc6cda3
JA
664
665 SIGRETURN (0);
666}
667
95732b49
JA
668#if defined (SIGWINCH)
669sighandler
670sigwinch_sighandler (sig)
671 int sig;
672{
673#if defined (MUST_REINSTALL_SIGHANDLERS)
674 set_signal_handler (SIGWINCH, sigwinch_sighandler);
675#endif /* MUST_REINSTALL_SIGHANDLERS */
676 sigwinch_received = 1;
677 SIGRETURN (0);
678}
679#endif /* SIGWINCH */
680
681void
682set_sigwinch_handler ()
683{
684#if defined (SIGWINCH)
685 old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
686#endif
687}
688
689void
690unset_sigwinch_handler ()
691{
692#if defined (SIGWINCH)
693 set_signal_handler (SIGWINCH, old_winch);
694#endif
695}
696
ac50fbac
CR
697sighandler
698sigterm_sighandler (sig)
699 int sig;
700{
701 sigterm_received = 1; /* XXX - counter? */
702 SIGRETURN (0);
703}
704
ccc6cda3
JA
705/* Signal functions used by the rest of the code. */
706#if !defined (HAVE_POSIX_SIGNALS)
707
ccc6cda3
JA
708/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
709sigprocmask (operation, newset, oldset)
710 int operation, *newset, *oldset;
711{
712 int old, new;
713
714 if (newset)
715 new = *newset;
716 else
717 new = 0;
718
719 switch (operation)
720 {
721 case SIG_BLOCK:
722 old = sigblock (new);
723 break;
724
725 case SIG_SETMASK:
ac50fbac 726 old = sigsetmask (new);
ccc6cda3
JA
727 break;
728
729 default:
b80f6443 730 internal_error (_("sigprocmask: %d: invalid operation"), operation);
ccc6cda3
JA
731 }
732
733 if (oldset)
734 *oldset = old;
735}
ccc6cda3
JA
736
737#else
738
739#if !defined (SA_INTERRUPT)
740# define SA_INTERRUPT 0
741#endif
742
743#if !defined (SA_RESTART)
744# define SA_RESTART 0
745#endif
746
747SigHandler *
748set_signal_handler (sig, handler)
749 int sig;
750 SigHandler *handler;
751{
752 struct sigaction act, oact;
753
754 act.sa_handler = handler;
755 act.sa_flags = 0;
495aee44
CR
756
757 /* XXX - bash-4.2 */
758 /* We don't want a child death to interrupt interruptible system calls, even
759 if we take the time to reap children */
ac50fbac 760#if defined (SIGCHLD)
30d188c2 761 if (sig == SIGCHLD)
495aee44 762 act.sa_flags |= SA_RESTART; /* XXX */
d233b485
CR
763#endif
764 /* Let's see if we can keep SIGWINCH from interrupting interruptible system
765 calls, like open(2)/read(2)/write(2) */
766#if defined (SIGWINCH)
767 if (sig == SIGWINCH)
768 act.sa_flags |= SA_RESTART; /* XXX */
ac50fbac
CR
769#endif
770 /* If we're installing a SIGTERM handler for interactive shells, we want
771 it to be as close to SIG_IGN as possible. */
772 if (sig == SIGTERM && handler == sigterm_sighandler)
773 act.sa_flags |= SA_RESTART; /* XXX */
495aee44 774
ccc6cda3
JA
775 sigemptyset (&act.sa_mask);
776 sigemptyset (&oact.sa_mask);
ac50fbac
CR
777 if (sigaction (sig, &act, &oact) == 0)
778 return (oact.sa_handler);
779 else
780 return (SIG_DFL);
ccc6cda3
JA
781}
782#endif /* HAVE_POSIX_SIGNALS */