diff options
author | Werner Koch <[email protected]> | 2008-12-17 19:42:17 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2008-12-17 19:42:17 +0000 |
commit | 6a09ba60cc7bbf0d0721e74ad48169328a05a5e1 (patch) | |
tree | 7584dfa8470ff483562b250b9380a2fa788e1975 | |
parent | Small doc fixes. (diff) | |
download | gnupg-6a09ba60cc7bbf0d0721e74ad48169328a05a5e1.tar.gz gnupg-6a09ba60cc7bbf0d0721e74ad48169328a05a5e1.zip |
Fix signal handling race condition.
Diffstat (limited to '')
-rw-r--r-- | agent/ChangeLog | 5 | ||||
-rw-r--r-- | agent/gpg-agent.c | 41 |
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); |