summaryrefslogtreecommitdiff
path: root/lib/readline/signals.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/readline/signals.c')
-rw-r--r--lib/readline/signals.c73
1 files changed, 57 insertions, 16 deletions
diff --git a/lib/readline/signals.c b/lib/readline/signals.c
index 055de2ee..f9174ab8 100644
--- a/lib/readline/signals.c
+++ b/lib/readline/signals.c
@@ -135,7 +135,7 @@ void *_rl_sigcleanarg;
/* Readline signal handler functions. */
-/* Called from RL_CHECK_SIGNALS() macro */
+/* Called from RL_CHECK_SIGNALS() macro to run signal handling code. */
RETSIGTYPE
_rl_signal_handler (int sig)
{
@@ -170,11 +170,16 @@ rl_signal_handler (int sig)
SIGHANDLER_RETURN;
}
+/* This is called to handle a signal when it is safe to do so (out of the
+ signal handler execution path). Called by _rl_signal_handler for all the
+ signals readline catches except SIGWINCH. */
static RETSIGTYPE
_rl_handle_signal (int sig)
{
+ int block_sig;
+
#if defined (HAVE_POSIX_SIGNALS)
- sigset_t set;
+ sigset_t set, oset;
#else /* !HAVE_POSIX_SIGNALS */
# if defined (HAVE_BSD_SIGNALS)
long omask;
@@ -204,7 +209,16 @@ _rl_handle_signal (int sig)
_rl_sigcleanup = 0;
_rl_sigcleanarg = 0;
}
-
+
+#if defined (HAVE_POSIX_SIGNALS)
+ /* Get the current set of blocked signals. If we want to block a signal for
+ the duration of the cleanup functions, make sure to add it to SET and
+ set block_sig = 1 (see the SIGHUP case below). */
+ block_sig = 0; /* sentinel to block signals with sigprocmask */
+ sigemptyset (&set);
+ sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
+#endif
+
switch (sig)
{
case SIGINT:
@@ -219,38 +233,60 @@ _rl_handle_signal (int sig)
#if defined (SIGTSTP)
case SIGTSTP:
case SIGTTIN:
+ case SIGTTOU:
# if defined (HAVE_POSIX_SIGNALS)
/* Block SIGTTOU so we can restore the terminal settings to something
sane without stopping on SIGTTOU if we have been placed into the
background. Even trying to get the current terminal pgrp with
- tcgetpgrp() will generate SIGTTOU, so we don't bother. Don't bother
- doing this if we've been stopped on SIGTTOU; it's already too late. */
- sigemptyset (&set);
+ tcgetpgrp() will generate SIGTTOU, so we don't bother. We still do
+ this even if we've been stopped on SIGTTOU, since we handle signals
+ when we have returned from the signal handler and the signal is no
+ longer blocked. */
sigaddset (&set, SIGTTOU);
- sigprocmask (SIG_BLOCK, &set, (sigset_t *)NULL);
+ block_sig = 1;
# endif
- case SIGTTOU:
#endif /* SIGTSTP */
- case SIGTERM:
+ /* Any signals that should be blocked during cleanup should go here. */
#if defined (SIGHUP)
case SIGHUP:
-#endif
+# if defined (_AIX)
+ if (block_sig == 0)
+ {
+ sigaddset (&set, sig);
+ block_sig = 1;
+ }
+# endif // _AIX
+#endif
+ /* Signals that don't require blocking during cleanup should go here. */
+ case SIGTERM:
#if defined (SIGALRM)
case SIGALRM:
#endif
#if defined (SIGQUIT)
case SIGQUIT:
#endif
+
+ if (block_sig)
+ sigprocmask (SIG_BLOCK, &set, &oset);
+
rl_echo_signal_char (sig);
rl_cleanup_after_signal ();
+ /* At this point, the application's signal handler, if any, is the
+ current handler. */
+
#if defined (HAVE_POSIX_SIGNALS)
-# if defined (SIGTSTP)
- /* Unblock SIGTTOU blocked above */
- if (sig == SIGTTIN || sig == SIGTSTP)
- sigprocmask (SIG_UNBLOCK, &set, (sigset_t *)NULL);
-# endif
+ /* Unblock any signal(s) blocked above */
+ if (block_sig)
+ sigprocmask (SIG_UNBLOCK, &oset, (sigset_t *)NULL);
+#endif
+ /* We don't have to bother unblocking the signal because we are not
+ running in a signal handler context. */
+#if 0
+#if defined (HAVE_POSIX_SIGNALS)
+ /* Make sure this signal is not blocked when we resend it to the
+ calling application. */
sigemptyset (&set);
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
sigdelset (&set, sig);
@@ -259,6 +295,7 @@ _rl_handle_signal (int sig)
omask = sigblock (0);
# endif /* HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
+#endif
#if defined (__EMX__)
signal (sig, SIG_ACK);
@@ -270,7 +307,10 @@ _rl_handle_signal (int sig)
raise (sig); /* assume we have raise */
#endif
- /* Let the signal that we just sent through. */
+ /* We don't need to modify the signal mask now that this is not run in
+ a signal handler context. */
+#if 0
+ /* Let the signal that we just sent through if it is blocked. */
#if defined (HAVE_POSIX_SIGNALS)
sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
#else /* !HAVE_POSIX_SIGNALS */
@@ -278,6 +318,7 @@ _rl_handle_signal (int sig)
sigsetmask (omask & ~(sigmask (sig)));
# endif /* HAVE_BSD_SIGNALS */
#endif /* !HAVE_POSIX_SIGNALS */
+#endif
rl_reset_after_signal ();
}