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:
parent
8d4af54ddd
commit
2abad7585a
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user