summaryrefslogtreecommitdiff
path: root/trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'trap.c')
-rw-r--r--trap.c98
1 files changed, 79 insertions, 19 deletions
diff --git a/trap.c b/trap.c
index 3cb67cdf..c7f8ded5 100644
--- a/trap.c
+++ b/trap.c
@@ -1,7 +1,7 @@
/* trap.c -- Not the trap command, but useful functions for manipulating
those objects. The trap command is in builtins/trap.def. */
-/* Copyright (C) 1987-2018 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -90,6 +90,7 @@ static void trap_if_untrapped (int, char *);
extern procenv_t alrmbuf;
extern volatile int from_return_trap;
+extern int waiting_for_child;
extern WORD_LIST *subst_assign_varlist;
@@ -120,6 +121,9 @@ int wait_signal_received;
int trapped_signal_received;
+/* Set to 1 to suppress the effect of `set v' in the DEBUG trap. */
+int suppress_debug_trap_verbose = 0;
+
#define GETORIGSIG(sig) \
do { \
original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
@@ -294,6 +298,7 @@ run_pending_traps ()
{
register int sig;
int old_exit_value, x;
+ int old_running;
WORD_LIST *save_subst_varlist;
HASH_TABLE *save_tempenv;
sh_parser_state_t pstate;
@@ -330,6 +335,7 @@ run_pending_traps ()
#if defined (ARRAY_VARS)
ps = save_pipestatus_array ();
#endif
+ old_running = running_trap;
for (sig = 1; sig < NSIG; sig++)
{
@@ -440,7 +446,7 @@ run_pending_traps ()
}
pending_traps[sig] = 0; /* XXX - move before evalstring? */
- running_trap = 0;
+ running_trap = old_running;
}
}
@@ -450,6 +456,17 @@ run_pending_traps ()
last_command_exit_value = old_exit_value;
}
+/* Set the private state variables noting that we received a signal SIG
+ for which we have a trap set. */
+void
+set_trap_state (sig)
+ int sig;
+{
+ catch_flag = 1;
+ pending_traps[sig]++;
+ trapped_signal_received = sig;
+}
+
sighandler
trap_handler (sig)
int sig;
@@ -478,14 +495,12 @@ trap_handler (sig)
set_signal_handler (sig, trap_handler);
#endif /* MUST_REINSTALL_SIGHANDLERS */
- catch_flag = 1;
- pending_traps[sig]++;
- trapped_signal_received = sig;
+ set_trap_state (sig);
if (this_shell_builtin && (this_shell_builtin == wait_builtin))
{
wait_signal_received = sig;
- if (interrupt_immediately && wait_intr_flag)
+ if (waiting_for_child && wait_intr_flag)
sh_longjmp (wait_intr_buf, 1);
}
@@ -493,13 +508,10 @@ trap_handler (sig)
/* Set the event hook so readline will call it after the signal handlers
finish executing, so if this interrupted character input we can get
quick response. */
- if (RL_ISSTATE (RL_STATE_SIGHANDLER) && interrupt_immediately == 0)
+ if (RL_ISSTATE (RL_STATE_SIGHANDLER))
bashline_set_event_hook ();
#endif
- if (interrupt_immediately)
- run_pending_traps ();
-
errno = oerrno;
}
@@ -507,16 +519,23 @@ trap_handler (sig)
}
int
-first_pending_trap ()
+next_pending_trap (start)
+ int start;
{
register int i;
- for (i = 1; i < NSIG; i++)
+ for (i = start; i < NSIG; i++)
if (pending_traps[i])
return i;
return -1;
}
+int
+first_pending_trap ()
+{
+ return (next_pending_trap (1));
+}
+
/* Return > 0 if any of the "real" signals (not fake signals like EXIT) are
trapped. */
int
@@ -531,6 +550,15 @@ any_signals_trapped ()
}
void
+clear_pending_traps ()
+{
+ register int i;
+
+ for (i = 1; i < NSIG; i++)
+ pending_traps[i] = 0;
+}
+
+void
check_signals ()
{
CHECK_ALRM; /* set by the read builtin */
@@ -952,6 +980,7 @@ void
run_trap_cleanup (sig)
int sig;
{
+ /* XXX - should we clean up trap_list[sig] == IMPOSSIBLE_TRAP_HANDLER? */
sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
}
@@ -966,7 +995,8 @@ _run_trap_internal (sig, tag)
{
char *trap_command, *old_trap;
int trap_exit_value;
- volatile int save_return_catch_flag, function_code, old_int;
+ volatile int save_return_catch_flag, function_code;
+ int old_modes, old_running, old_int;
int flags;
procenv_t save_return_catch;
WORD_LIST *save_subst_varlist;
@@ -976,13 +1006,15 @@ _run_trap_internal (sig, tag)
ARRAY *ps;
#endif
+ old_modes = old_running = -1;
+
trap_exit_value = function_code = 0;
trap_saved_exit_value = last_command_exit_value;
/* Run the trap only if SIG is trapped and not ignored, and we are not
currently executing in the trap handler. */
if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
(trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
-#if 0
+#if 1
/* Uncomment this to allow some special signals to recursively execute
trap handlers. */
(RECURSIVE_SIG (sig) || (sigmodes[sig] & SIG_INPROGRESS) == 0))
@@ -991,6 +1023,9 @@ _run_trap_internal (sig, tag)
#endif
{
old_trap = trap_list[sig];
+ old_modes = sigmodes[sig];
+ old_running = running_trap;
+
sigmodes[sig] |= SIG_INPROGRESS;
sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
trap_command = savestring (old_trap);
@@ -1050,8 +1085,10 @@ _run_trap_internal (sig, tag)
temporary_env = save_tempenv;
- sigmodes[sig] &= ~SIG_INPROGRESS;
- running_trap = 0;
+ if ((old_modes & SIG_INPROGRESS) == 0)
+ sigmodes[sig] &= ~SIG_INPROGRESS;
+
+ running_trap = old_running;
interrupt_state = old_int;
if (sigmodes[sig] & SIG_CHANGED)
@@ -1110,9 +1147,7 @@ run_debug_trap ()
#endif
old_verbose = echo_input_at_read;
-#if 0 /* not yet */
- echo_input_at_read = 0;
-#endif
+ echo_input_at_read = suppress_debug_trap_verbose ? 0 : echo_input_at_read;
trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
@@ -1177,6 +1212,8 @@ run_interrupt_trap (will_throw)
{
if (will_throw && running_trap > 0)
run_trap_cleanup (running_trap - 1);
+ pending_traps[SIGINT] = 0; /* run_pending_traps does this */
+ catch_flag = 0;
_run_trap_internal (SIGINT, "interrupt trap");
}
@@ -1391,3 +1428,26 @@ signal_in_progress (sig)
{
return (sigmodes[sig] & SIG_INPROGRESS);
}
+
+#if 0 /* TAG: bash-5.2 */
+int
+block_trapped_signals (maskp, omaskp)
+ sigset_t *maskp;
+ sigset_t *omaskp;
+{
+ int i;
+
+ sigemptyset (maskp);
+ for (i = 1; i < NSIG; i++)
+ if (sigmodes[i] & SIG_TRAPPED)
+ sigaddset (maskp, i);
+ return (sigprocmask (SIG_BLOCK, maskp, omaskp));
+}
+
+int
+unblock_trapped_signals (maskp)
+ sigset_t *maskp;
+{
+ return (sigprocmask (SIG_SETMASK, maskp, 0));
+}
+#endif