aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2008-12-17 19:42:17 +0000
committerWerner Koch <[email protected]>2008-12-17 19:42:17 +0000
commit6a09ba60cc7bbf0d0721e74ad48169328a05a5e1 (patch)
tree7584dfa8470ff483562b250b9380a2fa788e1975
parentSmall doc fixes. (diff)
downloadgnupg-6a09ba60cc7bbf0d0721e74ad48169328a05a5e1.tar.gz
gnupg-6a09ba60cc7bbf0d0721e74ad48169328a05a5e1.zip
Fix signal handling race condition.
Diffstat (limited to '')
-rw-r--r--agent/ChangeLog5
-rw-r--r--agent/gpg-agent.c41
2 files changed, 32 insertions, 14 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog
index 68d06e9f5..7a42fb875 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,3 +1,8 @@
+2008-12-17 Werner Koch <[email protected]>
+
+ * gpg-agent.c (handle_connections): Set action of all pth event
+ handled signals to SIG_IGN. Use a different pth_sigmask strategy.
+
2008-12-10 Werner Koch <[email protected]>
* command.c (cmd_get_passphrase): Implement option --no-ask.
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 21e4c4345..7d3fba09c 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -1748,13 +1748,28 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
#ifndef HAVE_W32_SYSTEM /* fixme */
/* Make sure that the signals we are going to handle are not blocked
- and create an event object for them. */
+ and create an event object for them. We also set the default
+ action to ignore because we use an Pth event to get notified
+ about signals. This avoids that the default action is taken in
+ case soemthing goes wrong within Pth. The problem might also be
+ a Pth bug. */
sigemptyset (&sigs );
- sigaddset (&sigs, SIGHUP);
- sigaddset (&sigs, SIGUSR1);
- sigaddset (&sigs, SIGUSR2);
- sigaddset (&sigs, SIGINT);
- sigaddset (&sigs, SIGTERM);
+ {
+ static const int mysigs[] = { SIGHUP, SIGUSR1, SIGUSR2, SIGINT, SIGTERM };
+ struct sigaction sa;
+ int i;
+
+ for (i=0; i < DIM (mysigs); i++)
+ {
+ sigemptyset (&sa.sa_mask);
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = 0;
+ sigaction (mysigs[i], &sa, NULL);
+
+ sigaddset (&sigs, mysigs[i]);
+ }
+ }
+
pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
#else
@@ -1782,8 +1797,10 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
for (;;)
{
- sigset_t oldsigs;
+ /* Make sure that our signals are not blocked. */
+ pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
+ /* Shutdown test. */
if (shutdown_pending)
{
if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1)
@@ -1843,7 +1860,7 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
log_error (_("pth_select failed: %s - waiting 1s\n"),
strerror (errno));
pth_sleep (1);
- continue;
+ continue;
}
if (pth_event_occurred (ev))
@@ -1862,11 +1879,11 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
handle_tick ();
}
-
+
/* We now might create new threads and because we don't want any
signals (as we are handling them here) to be delivered to a
new thread. Thus we need to block those signals. */
- pth_sigmask (SIG_BLOCK, &sigs, &oldsigs);
+ pth_sigmask (SIG_BLOCK, &sigs, NULL);
if (!shutdown_pending && FD_ISSET (FD2INT (listen_fd), &read_fdset))
{
@@ -1943,10 +1960,6 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
}
fd = GNUPG_INVALID_FD;
}
-
- /* Restore the signal mask. */
- pth_sigmask (SIG_SETMASK, &oldsigs, NULL);
-
}
pth_event_free (ev, PTH_FREE_ALL);