diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2017-03-03 12:30:56 +0100 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2017-03-03 12:40:06 +0100 |
commit | f9acc7d18bb90f47dafe7e32ae92f567756d6b12 (patch) | |
tree | 942f45d56aff704c8edce66d915db837be1fe0dc /scd/scdaemon.c | |
parent | gpg: Fix possible segv when attribute packets are filtered. (diff) | |
download | gnupg2-f9acc7d18bb90f47dafe7e32ae92f567756d6b12.tar.xz gnupg2-f9acc7d18bb90f47dafe7e32ae92f567756d6b12.zip |
scd: Fix scd_kick_the_loop.
* scd/scdaemon.c (notify_fd): Remove.
(the_event) [W32]: New.
(main_thread_pid) [!W32]: New.
(handle_signal): Handle SIGCONT.
(scd_kick_the_loop): Use signal on UNIX and event on Windows.
(handle_connections): Likewise.
--
Code with CreateEvent is copied from gpg-agent.c.
Code for signal is copied from dkg's gpg-agent-idling in Debian.
GnuPG-bug-id: 2982
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Diffstat (limited to 'scd/scdaemon.c')
-rw-r--r-- | scd/scdaemon.c | 87 |
1 files changed, 56 insertions, 31 deletions
diff --git a/scd/scdaemon.c b/scd/scdaemon.c index f7e9f83b5..4b63c9b4d 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -224,8 +224,12 @@ static char *redir_socket_name; POSIX systems). */ static assuan_sock_nonce_t socket_nonce; -/* FD to notify update of usb devices. */ -static int notify_fd; +#ifdef HAVE_W32_SYSTEM +static HANDLE the_event; +#else +/* PID to notify update of usb devices. */ +static pid_t main_thread_pid; +#endif static char *create_socket_name (char *standard_name); static gnupg_fd_t create_server_socket (const char *name, @@ -996,6 +1000,10 @@ handle_signal (int signo) log_info ("SIGUSR2 received - no action defined\n"); break; + case SIGCONT: + /* Nothing. */ + break; + case SIGTERM: if (!shutdown_pending) log_info ("SIGTERM received - shutting down ...\n"); @@ -1185,8 +1193,17 @@ scd_kick_the_loop (void) int ret; /* Kick the select loop. */ - ret = write (notify_fd, "", 1); - (void)ret; +#ifdef HAVE_W32_SYSTEM + ret = SetEvent (the_event); + if (ret == 0) + log_error ("SetEvent for scd_kick_the_loop failed: %s\n", + w32_strerror (-1)); +#else + ret = kill (main_thread_pid, SIGCONT); + if (ret < 0) + log_error ("SetEvent for scd_kick_the_loop failed: %s\n", + gpg_strerror (gpg_error_from_syserror ())); +#endif } /* Connection handler loop. Wait for connection requests and spawn a @@ -1206,18 +1223,12 @@ handle_connections (int listen_fd) struct timespec timeout; struct timespec *t; int saved_errno; -#ifndef HAVE_W32_SYSTEM +#ifdef HAVE_W32_SYSTEM + HANDLE events[2]; + unsigned int events_set; +#else int signo; #endif - int pipe_fd[2]; - - ret = gnupg_create_pipe (pipe_fd); - if (ret) - { - log_error ("pipe creation failed: %s\n", gpg_strerror (ret)); - return; - } - notify_fd = pipe_fd[1]; ret = npth_attr_init(&tattr); if (ret) @@ -1228,14 +1239,40 @@ handle_connections (int listen_fd) npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED); -#ifndef HAVE_W32_SYSTEM +#ifdef HAVE_W32_SYSTEM + { + HANDLE h, h2; + SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE}; + + events[0] = the_event = INVALID_HANDLE_VALUE; + events[1] = INVALID_HANDLE_VALUE; + h = CreateEvent (&sa, TRUE, FALSE, NULL); + if (!h) + log_error ("can't create scd event: %s\n", w32_strerror (-1) ); + else if (!DuplicateHandle (GetCurrentProcess(), h, + GetCurrentProcess(), &h2, + EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0)) + { + log_error ("setting synchronize for scd_kick_the_loop failed: %s\n", + w32_strerror (-1) ); + CloseHandle (h); + } + else + { + CloseHandle (h); + events[0] = the_event = h2; + } + } +#else npth_sigev_init (); npth_sigev_add (SIGHUP); npth_sigev_add (SIGUSR1); npth_sigev_add (SIGUSR2); npth_sigev_add (SIGINT); + npth_sigev_add (SIGCONT); npth_sigev_add (SIGTERM); npth_sigev_fini (); + main_thread_pid = getpid (); #endif FD_ZERO (&fdset); @@ -1246,10 +1283,6 @@ handle_connections (int listen_fd) nfd = listen_fd; } - FD_SET (pipe_fd[0], &fdset); - if (nfd < pipe_fd[0]) - nfd = pipe_fd[0]; - for (;;) { int periodical_check; @@ -1264,8 +1297,6 @@ handle_connections (int listen_fd) file descriptors to wait for, so that the select will be used to just wait on a signal or timeout event. */ FD_ZERO (&fdset); - FD_SET (pipe_fd[0], &fdset); - nfd = pipe_fd[0]; listen_fd = -1; } @@ -1291,8 +1322,11 @@ handle_connections (int listen_fd) while (npth_sigev_get_pending(&signo)) handle_signal (signo); #else - ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, t, NULL, NULL); + ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, t, + events, &events_set); saved_errno = errno; + if (events_set & 1) + continue; #endif if (ret == -1 && saved_errno != EINTR) @@ -1307,13 +1341,6 @@ handle_connections (int listen_fd) /* Timeout. Will be handled when calculating the next timeout. */ continue; - if (FD_ISSET (pipe_fd[0], &read_fdset)) - { - char buf[256]; - - ret = read (pipe_fd[0], buf, sizeof buf); - } - if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset)) { ctrl_t ctrl; @@ -1351,8 +1378,6 @@ handle_connections (int listen_fd) } } - close (pipe_fd[0]); - close (pipe_fd[1]); cleanup (); log_info (_("%s %s stopped\n"), strusage(11), strusage(13)); npth_attr_destroy (&tattr); |