1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-03-12 23:01:14 +01:00

agent: Add agent_kick_the_loop function.

* agent/agent.h (agent_kick_the_loop): New.
* agent/gpg-agent.c [HAVE_W32_SYSTEM] (the_event2): New.
[HAVE_PSELECT_NO_EINTR] (event_pipe_fd): New.
[!HAVE_PSELECT_NO_EINTR] (main_thread_pid): New.
(create_an_event): New, factored out.
(get_agent_daemon_notify_event): Use create_an_event.
(handle_signal): Add a case for SIGCONT.
(agent_kick_the_loop): New.
(handle_connections): Call pselect possibly with the pipe.
Call eselect with THE_EVENT2.

--

GnuPG-bug-id: 6682
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2023-08-24 16:07:26 +09:00
parent 9e4d522239
commit 716e59b0b6
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
2 changed files with 117 additions and 34 deletions

View File

@ -411,6 +411,7 @@ void *get_agent_daemon_notify_event (void);
#endif #endif
void agent_sighup_action (void); void agent_sighup_action (void);
int map_pk_openpgp_to_gcry (int openpgp_algo); int map_pk_openpgp_to_gcry (int openpgp_algo);
void agent_kick_the_loop (void);
/*-- command.c --*/ /*-- command.c --*/
gpg_error_t agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid, gpg_error_t agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid,

View File

@ -432,6 +432,17 @@ static assuan_sock_nonce_t socket_nonce_ssh;
* Let's try this as default. Change at runtime with --listen-backlog. */ * Let's try this as default. Change at runtime with --listen-backlog. */
static int listen_backlog = 64; static int listen_backlog = 64;
#ifdef HAVE_W32_SYSTEM
/* The event to break the select call. */
static HANDLE the_event2;
#elif defined(HAVE_PSELECT_NO_EINTR)
/* An FD to break the select call. */
static int event_pipe_fd;
#else
/* PID of the main thread. */
static pid_t main_thread_pid;
#endif
/* Default values for options passed to the pinentry. */ /* Default values for options passed to the pinentry. */
static char *default_display; static char *default_display;
static char *default_ttyname; static char *default_ttyname;
@ -2130,13 +2141,9 @@ get_agent_active_connection_count (void)
notification event. Calling it the first time creates that notification event. Calling it the first time creates that
event. */ event. */
#if defined(HAVE_W32_SYSTEM) #if defined(HAVE_W32_SYSTEM)
void * static void *
get_agent_daemon_notify_event (void) create_an_event (void)
{ {
static HANDLE the_event = INVALID_HANDLE_VALUE;
if (the_event == INVALID_HANDLE_VALUE)
{
HANDLE h, h2; HANDLE h, h2;
SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE}; SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
@ -2148,22 +2155,32 @@ get_agent_daemon_notify_event (void)
the WFMO. */ the WFMO. */
h = CreateEvent (&sa, TRUE, FALSE, NULL); h = CreateEvent (&sa, TRUE, FALSE, NULL);
if (!h) if (!h)
log_error ("can't create scd notify event: %s\n", w32_strerror (-1) ); log_error ("can't create an event: %s\n", w32_strerror (-1) );
else if (!DuplicateHandle (GetCurrentProcess(), h, else if (!DuplicateHandle (GetCurrentProcess(), h,
GetCurrentProcess(), &h2, GetCurrentProcess(), &h2,
EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0)) EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
{ {
log_error ("setting synchronize for scd notify event failed: %s\n", log_error ("setting synchronize for an event failed: %s\n",
w32_strerror (-1) ); w32_strerror (-1) );
CloseHandle (h); CloseHandle (h);
} }
else else
{ {
CloseHandle (h); CloseHandle (h);
the_event = h2; return h2;
}
} }
return INVALID_HANDLE_VALUE;
}
void *
get_agent_daemon_notify_event (void)
{
static HANDLE the_event = INVALID_HANDLE_VALUE;
if (the_event == INVALID_HANDLE_VALUE)
the_event = create_an_event ();
return the_event; return the_event;
} }
#endif /*HAVE_W32_SYSTEM*/ #endif /*HAVE_W32_SYSTEM*/
@ -2528,6 +2545,11 @@ handle_signal (int signo)
agent_sigusr2_action (); agent_sigusr2_action ();
break; break;
case SIGCONT:
/* Do nothing, but break the syscall. */
log_debug ("SIGCONT received - breaking select\n");
break;
case SIGTERM: case SIGTERM:
if (!shutdown_pending) if (!shutdown_pending)
log_info ("SIGTERM received - shutting down ...\n"); log_info ("SIGTERM received - shutting down ...\n");
@ -2959,6 +2981,28 @@ start_connection_thread_ssh (void *arg)
} }
void
agent_kick_the_loop (void)
{
/* Kick the select loop. */
#ifdef HAVE_W32_SYSTEM
int ret = SetEvent (the_event2);
if (ret == 0)
log_error ("SetEvent for agent_kick_the_loop failed: %s\n",
w32_strerror (-1));
#else
# ifdef HAVE_PSELECT_NO_EINTR
write (event_pipe_fd, "", 1);
# else
int ret = kill (main_thread_pid, SIGCONT);
if (ret < 0)
log_error ("sending signal for agent_kick_the_loop failed: %s\n",
gpg_strerror (gpg_error_from_syserror ()));
# endif
#endif
}
/* Connection handler loop. Wait for connection requests and spawn a /* Connection handler loop. Wait for connection requests and spawn a
thread after accepting a connection. */ thread after accepting a connection. */
static void static void
@ -2980,8 +3024,13 @@ handle_connections (gnupg_fd_t listen_fd,
struct timespec curtime; struct timespec curtime;
struct timespec timeout; struct timespec timeout;
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
HANDLE events[2]; HANDLE events[3];
unsigned int events_set; unsigned int events_set;
#else
int signo;
# ifdef HAVE_PSELECT_NO_EINTR
int pipe_fd[2];
# endif
#endif #endif
int sock_inotify_fd = -1; int sock_inotify_fd = -1;
int home_inotify_fd = -1; int home_inotify_fd = -1;
@ -3009,11 +3058,24 @@ handle_connections (gnupg_fd_t listen_fd,
npth_sigev_add (SIGUSR1); npth_sigev_add (SIGUSR1);
npth_sigev_add (SIGUSR2); npth_sigev_add (SIGUSR2);
npth_sigev_add (SIGINT); npth_sigev_add (SIGINT);
npth_sigev_add (SIGCONT);
npth_sigev_add (SIGTERM); npth_sigev_add (SIGTERM);
npth_sigev_fini (); npth_sigev_fini ();
# ifdef HAVE_PSELECT_NO_EINTR
ret = gnupg_create_pipe (pipe_fd);
if (ret)
{
log_error ("pipe creation failed: %s\n", gpg_strerror (ret));
return;
}
event_pipe_fd = pipe_fd[1];
# else
main_thread_pid = getpid ();
# endif
#else #else
events[0] = get_agent_daemon_notify_event (); events[0] = get_agent_daemon_notify_event ();
events[1] = INVALID_HANDLE_VALUE; events[1] = the_event2 = create_an_event ();
events[2] = INVALID_HANDLE_VALUE;
#endif #endif
if (disable_check_own_socket) if (disable_check_own_socket)
@ -3140,6 +3202,12 @@ handle_connections (gnupg_fd_t listen_fd,
thus a simple assignment is fine to copy the entire set. */ thus a simple assignment is fine to copy the entire set. */
read_fdset = fdset; read_fdset = fdset;
#ifdef HAVE_PSELECT_NO_EINTR
FD_SET (pipe_fd[0], &read_fdset);
if (nfd < pipe_fd[0])
nfd = pipe_fd[0];
#endif
npth_clock_gettime (&curtime); npth_clock_gettime (&curtime);
if (!(npth_timercmp (&curtime, &abstime, <))) if (!(npth_timercmp (&curtime, &abstime, <)))
{ {
@ -3155,11 +3223,8 @@ handle_connections (gnupg_fd_t listen_fd,
npth_sigev_sigmask ()); npth_sigev_sigmask ());
saved_errno = errno; saved_errno = errno;
{
int signo;
while (npth_sigev_get_pending (&signo)) while (npth_sigev_get_pending (&signo))
handle_signal (signo); handle_signal (signo);
}
#else #else
ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout, ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout,
events, &events_set); events, &events_set);
@ -3182,6 +3247,15 @@ handle_connections (gnupg_fd_t listen_fd,
next timeout. */ next timeout. */
continue; continue;
#ifdef HAVE_PSELECT_NO_EINTR
if (FD_ISSET (pipe_fd[0], &read_fdset))
{
char buf[256];
read (pipe_fd[0], buf, sizeof buf);
}
#endif
/* The inotify fds are set even when a shutdown is pending (see /* The inotify fds are set even when a shutdown is pending (see
* above). So we must handle them in any case. To avoid that * above). So we must handle them in any case. To avoid that
* they trigger a second time we close them immediately. */ * they trigger a second time we close them immediately. */
@ -3259,6 +3333,14 @@ handle_connections (gnupg_fd_t listen_fd,
close (sock_inotify_fd); close (sock_inotify_fd);
if (home_inotify_fd != -1) if (home_inotify_fd != -1)
close (home_inotify_fd); close (home_inotify_fd);
#ifdef HAVE_W32_SYSTEM
if (the_event2 != INVALID_HANDLE_VALUE)
CloseHandle (the_event2);
#endif
#ifdef HAVE_PSELECT_NO_EINTR
close (pipe_fd[0]);
close (pipe_fd[1]);
#endif
cleanup (); cleanup ();
log_info (_("%s %s stopped\n"), gpgrt_strusage(11), gpgrt_strusage(13)); log_info (_("%s %s stopped\n"), gpgrt_strusage(11), gpgrt_strusage(13));
npth_attr_destroy (&tattr); npth_attr_destroy (&tattr);