/* sig.c - interface for shell signal handlers and signal initialization. */
-/* Copyright (C) 1994-2006 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
- Bash is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2, or (at your option) any later
- version.
+ Bash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- Bash is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
+ Bash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with Bash; see the file COPYING. If not, write to the Free Software
- Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+ You should have received a copy of the GNU General Public License
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
+*/
#include "config.h"
extern int last_command_exit_value;
extern int last_command_exit_signal;
extern int return_catch_flag;
-extern int loop_level, continuing, breaking;
+extern int loop_level, continuing, breaking, funcnest;
+extern int executing_list;
+extern int comsub_ignore_return;
extern int parse_and_execute_level, shell_initialized;
+#if defined (HISTORY)
+extern int history_lines_this_session;
+#endif
+
+extern void initialize_siglist ();
/* Non-zero after SIGINT. */
volatile int interrupt_state = 0;
/* Initialize signals that will terminate the shell to do some
unwind protection. For non-interactive shells, we only call
- this when a trap is defined for EXIT (0). */
+ this when a trap is defined for EXIT (0) or when trap is run
+ to display signal dispositions. */
void
initialize_terminating_signals ()
{
XSAFLAGS(i) = oact.sa_flags;
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
- if (!interactive_shell && XHANDLER (i) == SIG_IGN)
+ /* XXX - should we do this for interactive shells, too? */
+ if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
{
sigaction (XSIG (i), &oact, &act);
set_signal_ignored (XSIG (i));
XSAFLAGS(i) = 0;
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
- if (!interactive_shell && XHANDLER (i) == SIG_IGN)
+ /* XXX - should we do this for interactive shells, too? */
+ if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
{
signal (XSIG (i), SIG_IGN);
set_signal_ignored (XSIG (i));
#endif /* PROCESS_SUBSTITUTION */
run_unwind_protects ();
- loop_level = continuing = breaking = 0;
- return_catch_flag = 0;
+ loop_level = continuing = breaking = funcnest = 0;
+ executing_list = comsub_ignore_return = return_catch_flag = 0;
}
/* What to do when we've been interrupted, and it is safe to handle it. */
/* Run any traps set on SIGINT. */
run_interrupt_trap ();
- /* Cleanup string parser environment. */
+ /* Clean up string parser environment. */
while (parse_and_execute_level)
parse_and_execute_cleanup ();
#if defined (READLINE)
if (interactive)
- bashline_reinitialize ();
+ bashline_reset ();
#endif /* READLINE */
#if defined (PROCESS_SUBSTITUTION)
#endif /* PROCESS_SUBSTITUTION */
run_unwind_protects ();
- loop_level = continuing = breaking = 0;
- return_catch_flag = 0;
+ loop_level = continuing = breaking = funcnest = 0;
+ executing_list = comsub_ignore_return = return_catch_flag = 0;
if (interactive && print_newline)
{
termsig_sighandler (sig)
int sig;
{
+ /* If we get called twice with the same signal before handling it,
+ terminate right away. */
+ if (
+#ifdef SIGHUP
+ sig != SIGHUP &&
+#endif
+#ifdef SIGINT
+ sig != SIGINT &&
+#endif
+#ifdef SIGDANGER
+ sig != SIGDANGER &&
+#endif
+#ifdef SIGPIPE
+ sig != SIGPIPE &&
+#endif
+#ifdef SIGALRM
+ sig != SIGALRM &&
+#endif
+#ifdef SIGTERM
+ sig != SIGTERM &&
+#endif
+#ifdef SIGXCPU
+ sig != SIGXCPU &&
+#endif
+#ifdef SIGXFSZ
+ sig != SIGXFSZ &&
+#endif
+#ifdef SIGVTALRM
+ sig != SIGVTALRM &&
+#endif
+#ifdef SIGLOST
+ sig != SIGLOST &&
+#endif
+#ifdef SIGUSR1
+ sig != SIGUSR1 &&
+#endif
+#ifdef SIGUSR2
+ sig != SIGUSR2 &&
+#endif
+ sig == terminating_signal)
+ terminate_immediately = 1;
+
terminating_signal = sig;
+ /* XXX - should this also trigger when interrupt_immediately is set? */
if (terminate_immediately)
{
+#if defined (HISTORY)
+ /* XXX - will inhibit history file being written */
+ history_lines_this_session = 0;
+#endif
terminate_immediately = 0;
termsig_handler (sig);
}
#endif /* HISTORY */
#if defined (JOB_CONTROL)
- if (interactive && sig == SIGHUP)
+ if (sig == SIGHUP && (interactive || (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB))))
hangup_all_jobs ();
end_job_control ();
#endif /* JOB_CONTROL */
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
+ /* Reset execution context */
+ loop_level = continuing = breaking = funcnest = 0;
+ executing_list = comsub_ignore_return = return_catch_flag = 0;
+
run_exit_trap ();
set_signal_handler (sig, SIG_DFL);
kill (getpid (), sig);
if (interrupt_immediately)
{
interrupt_immediately = 0;
+ last_command_exit_value = 128 + sig;
throw_to_top_level ();
}
act.sa_handler = handler;
act.sa_flags = 0;
-#if 0
- if (sig == SIGALRM)
- act.sa_flags |= SA_INTERRUPT; /* XXX */
- else
+
+ /* XXX - bash-4.2 */
+ /* We don't want a child death to interrupt interruptible system calls, even
+ if we take the time to reap children */
+ if (sig == SIGCHLD)
act.sa_flags |= SA_RESTART; /* XXX */
-#endif
+
sigemptyset (&act.sa_mask);
sigemptyset (&oact.sa_mask);
sigaction (sig, &act, &oact);