mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-11 22:01:08 +02:00
agent: Have a thread to wait for the child process of scdaemon.
* agent/call-scd.c (wait_child_thread): New. (start_scd): Create a thread for wait_child_thread. (agent_scd_check_aliveness): Remove. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
9fb3f0f3f7
commit
40c7923ea8
@ -546,7 +546,6 @@ int divert_writekey (ctrl_t ctrl, int force, const char *serialno,
|
|||||||
void initialize_module_call_scd (void);
|
void initialize_module_call_scd (void);
|
||||||
void agent_scd_dump_state (void);
|
void agent_scd_dump_state (void);
|
||||||
int agent_scd_check_running (void);
|
int agent_scd_check_running (void);
|
||||||
void agent_scd_check_aliveness (void);
|
|
||||||
int agent_reset_scd (ctrl_t ctrl);
|
int agent_reset_scd (ctrl_t ctrl);
|
||||||
int agent_card_learn (ctrl_t ctrl,
|
int agent_card_learn (ctrl_t ctrl,
|
||||||
void (*kpinfo_cb)(void*, const char *),
|
void (*kpinfo_cb)(void*, const char *),
|
||||||
|
182
agent/call-scd.c
182
agent/call-scd.c
@ -207,6 +207,85 @@ atfork_cb (void *opaque, int where)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
wait_child_thread (void *arg)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct scd_local_s *sl;
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
HANDLE pid = (HANDLE)arg;
|
||||||
|
|
||||||
|
npth_unprotect ();
|
||||||
|
WaitForSingleObject ((HANDLE)pid, INFINITE);
|
||||||
|
npth_protect ();
|
||||||
|
#else
|
||||||
|
int wstatus;
|
||||||
|
pid_t pid = (pid_t)(uintptr_t)arg;
|
||||||
|
|
||||||
|
again:
|
||||||
|
npth_unprotect ();
|
||||||
|
err = waitpid (pid, &wstatus, 0);
|
||||||
|
npth_protect ();
|
||||||
|
|
||||||
|
if (err < 0)
|
||||||
|
{
|
||||||
|
if (errno == EINTR)
|
||||||
|
goto again;
|
||||||
|
log_error ("waitpid failed: %s\n", strerror (errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (WIFEXITED (wstatus))
|
||||||
|
log_info ("scdaemon finished (status %d)\n", WEXITSTATUS (wstatus));
|
||||||
|
else if (WIFSIGNALED (wstatus))
|
||||||
|
log_info ("scdaemon killed by signal %d\n", WTERMSIG (wstatus));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (WIFSTOPPED (wstatus))
|
||||||
|
log_info ("scdaemon stopped by signal %d\n", WSTOPSIG (wstatus));
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
err = npth_mutex_lock (&start_scd_lock);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("failed to acquire the start_scd lock: %s\n",
|
||||||
|
strerror (err));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assuan_set_flag (primary_scd_ctx, ASSUAN_NO_WAITPID, 1);
|
||||||
|
|
||||||
|
for (sl = scd_local_list; sl; sl = sl->next_local)
|
||||||
|
{
|
||||||
|
sl->invalid = 1;
|
||||||
|
if (!sl->in_use && sl->ctx)
|
||||||
|
{
|
||||||
|
assuan_release (sl->ctx);
|
||||||
|
sl->ctx = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
primary_scd_ctx = NULL;
|
||||||
|
primary_scd_ctx_reusable = 0;
|
||||||
|
|
||||||
|
xfree (socket_name);
|
||||||
|
socket_name = NULL;
|
||||||
|
|
||||||
|
err = npth_mutex_unlock (&start_scd_lock);
|
||||||
|
if (err)
|
||||||
|
log_error ("failed to release the start_scd lock while"
|
||||||
|
" doing the aliveness check: %s\n", strerror (err));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Fork off the SCdaemon if this has not already been done. Lock the
|
/* Fork off the SCdaemon if this has not already been done. Lock the
|
||||||
daemon and make sure that a proper context has been setup in CTRL.
|
daemon and make sure that a proper context has been setup in CTRL.
|
||||||
This function might also lock the daemon, which means that the
|
This function might also lock the daemon, which means that the
|
||||||
@ -427,6 +506,24 @@ start_scd (ctrl_t ctrl)
|
|||||||
primary_scd_ctx = ctx;
|
primary_scd_ctx = ctx;
|
||||||
primary_scd_ctx_reusable = 0;
|
primary_scd_ctx_reusable = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
npth_t thread;
|
||||||
|
npth_attr_t tattr;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
pid = assuan_get_pid (primary_scd_ctx);
|
||||||
|
err = npth_attr_init (&tattr);
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
|
||||||
|
err = npth_create (&thread, &tattr, wait_child_thread,
|
||||||
|
(void *)(uintptr_t)pid);
|
||||||
|
if (err)
|
||||||
|
log_error ("error spawning wait_child_thread: %s\n", strerror (err));
|
||||||
|
npth_attr_destroy (&tattr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
xfree (abs_homedir);
|
xfree (abs_homedir);
|
||||||
if (err)
|
if (err)
|
||||||
@ -456,91 +553,6 @@ agent_scd_check_running (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check whether the Scdaemon is still alive and clean it up if not. */
|
|
||||||
void
|
|
||||||
agent_scd_check_aliveness (void)
|
|
||||||
{
|
|
||||||
pid_t pid;
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
DWORD rc;
|
|
||||||
#else
|
|
||||||
int rc;
|
|
||||||
#endif
|
|
||||||
struct timespec abstime;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (!primary_scd_ctx)
|
|
||||||
return; /* No scdaemon running. */
|
|
||||||
|
|
||||||
/* This is not a critical function so we use a short timeout while
|
|
||||||
acquiring the lock. */
|
|
||||||
npth_clock_gettime (&abstime);
|
|
||||||
abstime.tv_sec += 1;
|
|
||||||
err = npth_mutex_timedlock (&start_scd_lock, &abstime);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
if (err == ETIMEDOUT)
|
|
||||||
{
|
|
||||||
if (opt.verbose > 1)
|
|
||||||
log_info ("failed to acquire the start_scd lock while"
|
|
||||||
" doing an aliveness check: %s\n", strerror (err));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
log_error ("failed to acquire the start_scd lock while"
|
|
||||||
" doing an aliveness check: %s\n", strerror (err));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (primary_scd_ctx)
|
|
||||||
{
|
|
||||||
pid = assuan_get_pid (primary_scd_ctx);
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
|
||||||
/* If we have a PID we disconnect if either GetExitProcessCode
|
|
||||||
fails or if ir returns the exit code of the scdaemon. 259 is
|
|
||||||
the error code for STILL_ALIVE. */
|
|
||||||
if (pid != (pid_t)(void*)(-1) && pid
|
|
||||||
&& (!GetExitCodeProcess ((HANDLE)pid, &rc) || rc != 259))
|
|
||||||
#else
|
|
||||||
if (pid != (pid_t)(-1) && pid
|
|
||||||
&& ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* Okay, scdaemon died. Disconnect the primary connection
|
|
||||||
now but take care that it won't do another wait. Also
|
|
||||||
cleanup all other connections and release their
|
|
||||||
resources. The next use will start a new daemon then.
|
|
||||||
Due to the use of the START_SCD_LOCK we are sure that
|
|
||||||
none of these context are actually in use. */
|
|
||||||
struct scd_local_s *sl;
|
|
||||||
|
|
||||||
assuan_set_flag (primary_scd_ctx, ASSUAN_NO_WAITPID, 1);
|
|
||||||
|
|
||||||
for (sl=scd_local_list; sl; sl = sl->next_local)
|
|
||||||
{
|
|
||||||
sl->invalid = 1;
|
|
||||||
if (!sl->in_use && sl->ctx)
|
|
||||||
{
|
|
||||||
assuan_release (sl->ctx);
|
|
||||||
sl->ctx = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
primary_scd_ctx = NULL;
|
|
||||||
primary_scd_ctx_reusable = 0;
|
|
||||||
|
|
||||||
xfree (socket_name);
|
|
||||||
socket_name = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = npth_mutex_unlock (&start_scd_lock);
|
|
||||||
if (err)
|
|
||||||
log_error ("failed to release the start_scd lock while"
|
|
||||||
" doing the aliveness check: %s\n", strerror (err));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Reset the SCD if it has been used. Actually it is not a reset but
|
/* Reset the SCD if it has been used. Actually it is not a reset but
|
||||||
a cleanup of resources used by the current connection. */
|
a cleanup of resources used by the current connection. */
|
||||||
int
|
int
|
||||||
|
@ -2370,9 +2370,6 @@ handle_tick (void)
|
|||||||
if (!last_minute)
|
if (!last_minute)
|
||||||
last_minute = time (NULL);
|
last_minute = time (NULL);
|
||||||
|
|
||||||
/* Check whether the scdaemon has died and cleanup in this case. */
|
|
||||||
agent_scd_check_aliveness ();
|
|
||||||
|
|
||||||
/* If we are running as a child of another process, check whether
|
/* If we are running as a child of another process, check whether
|
||||||
the parent is still alive and shutdown if not. */
|
the parent is still alive and shutdown if not. */
|
||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
Loading…
x
Reference in New Issue
Block a user