1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-06-14 18:31:03 +02:00

agent: Fix detection of exit of scdaemon.

* agent/call-scd.c (start_scd): Acquire START_SCD_LOCK for
SCD_LOCAL_LIST.  Move common case code to fast path.
Release START_SCD_LOCK before calling unlock_scd.
When new CTX is allocated, clear INVALID flag.
(agent_reset_scd): Serialize the access to SCD_LOCAL_LIST by
START_SCD_LOCK.

--

GnuPG-bug-id: 4377
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2019-03-06 10:33:54 +09:00
parent 8d4af54ddd
commit 2abad7585a

View File

@ -303,33 +303,19 @@ start_scd (ctrl_t ctrl)
if (opt.disable_scdaemon) if (opt.disable_scdaemon)
return gpg_error (GPG_ERR_NOT_SUPPORTED); return gpg_error (GPG_ERR_NOT_SUPPORTED);
/* If this is the first call for this session, setup the local data if (ctrl->scd_local && ctrl->scd_local->ctx)
structure. */
if (!ctrl->scd_local)
{ {
ctrl->scd_local = xtrycalloc (1, sizeof *ctrl->scd_local); ctrl->scd_local->in_use = 1;
if (!ctrl->scd_local) return 0; /* Okay, the context is fine. */
return gpg_error_from_syserror ();
ctrl->scd_local->next_local = scd_local_list;
scd_local_list = ctrl->scd_local;
} }
if (ctrl->scd_local->in_use) if (ctrl->scd_local && ctrl->scd_local->in_use)
{ {
log_error ("start_scd: CTX is in use\n"); log_error ("start_scd: CTX is in use\n");
return gpg_error (GPG_ERR_INTERNAL); return gpg_error (GPG_ERR_INTERNAL);
} }
ctrl->scd_local->in_use = 1;
if (ctrl->scd_local->ctx) /* We need to serialize the access to scd_local_list and primary_scd_ctx. */
return 0; /* Okay, the context is fine. We used to test for an
alive context here and do an disconnect. Now that we
have a ticker function to check for it, it is easier
not to check here but to let the connection run on an
error instead. */
/* We need to protect the following code. */
rc = npth_mutex_lock (&start_scd_lock); rc = npth_mutex_lock (&start_scd_lock);
if (rc) if (rc)
{ {
@ -338,6 +324,25 @@ start_scd (ctrl_t ctrl)
return gpg_error (GPG_ERR_INTERNAL); return gpg_error (GPG_ERR_INTERNAL);
} }
/* If this is the first call for this session, setup the local data
structure. */
if (!ctrl->scd_local)
{
ctrl->scd_local = xtrycalloc (1, sizeof *ctrl->scd_local);
if (!ctrl->scd_local)
{
err = gpg_error_from_syserror ();
rc = npth_mutex_unlock (&start_scd_lock);
if (rc)
log_error ("failed to release the start_scd lock: %s\n", strerror (rc));
return err;
}
ctrl->scd_local->next_local = scd_local_list;
scd_local_list = ctrl->scd_local;
}
ctrl->scd_local->in_use = 1;
/* Check whether the pipe server has already been started and in /* Check whether the pipe server has already been started and in
this case either reuse a lingering pipe connection or establish a this case either reuse a lingering pipe connection or establish a
new socket based one. */ new socket based one. */
@ -522,6 +527,10 @@ start_scd (ctrl_t ctrl)
} }
leave: leave:
rc = npth_mutex_unlock (&start_scd_lock);
if (rc)
log_error ("failed to release the start_scd lock: %s\n", strerror (rc));
xfree (abs_homedir); xfree (abs_homedir);
if (err) if (err)
{ {
@ -531,11 +540,9 @@ start_scd (ctrl_t ctrl)
} }
else else
{ {
ctrl->scd_local->invalid = 0;
ctrl->scd_local->ctx = ctx; ctrl->scd_local->ctx = ctx;
} }
rc = npth_mutex_unlock (&start_scd_lock);
if (rc)
log_error ("failed to release the start_scd lock: %s\n", strerror (rc));
return err; return err;
} }
@ -554,15 +561,21 @@ agent_scd_check_running (void)
a cleanup of resources used by the current connection. */ a cleanup of resources used by the current connection. */
int int
agent_reset_scd (ctrl_t ctrl) agent_reset_scd (ctrl_t ctrl)
{
int err = npth_mutex_lock (&start_scd_lock);
if (err)
{
log_error ("failed to acquire the start_scd lock: %s\n",
strerror (err));
}
else
{ {
if (ctrl->scd_local) if (ctrl->scd_local)
{ {
if (ctrl->scd_local->ctx) if (ctrl->scd_local->ctx)
{ {
/* We can't disconnect the primary context because libassuan /* We send a reset and keep that connection for reuse. */
does a waitpid on it and thus the system would hang.
Instead we send a reset and keep that connection for
reuse. */
if (ctrl->scd_local->ctx == primary_scd_ctx) if (ctrl->scd_local->ctx == primary_scd_ctx)
{ {
/* Send a RESTART to the SCD. This is required for the /* Send a RESTART to the SCD. This is required for the
@ -604,6 +617,11 @@ agent_reset_scd (ctrl_t ctrl)
ctrl->scd_local = NULL; ctrl->scd_local = NULL;
} }
err = npth_mutex_unlock (&start_scd_lock);
if (err)
log_error ("failed to release the start_scd lock: %s\n", strerror (err));
}
return 0; return 0;
} }