mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
scd: Fix problem with reader list becoming empty.
* scd/apdu.c (close_pcsc_reader): Do not decrement refcount if already zero. Always release context if or becomes zero. (apdu_dev_list_start): Unlock prior to close_pcsc_reader. For PC/SC increment the count. Always release the lock. (apdu_dev_list_finish): No more unlocking. Use close_pcsc_reader instead of code duplication. * scd/apdu.c (pcsc_error_string): Add an error code. * scd/scdaemon.c (scd_kick_the_loop): Fix a diagnostic. -- There was an obvious bug in that the pcsc.count could go below zero and thus there was no chance to get the context release. Releasing and recreating the context is at least under Windows important to get rit of the PCSC_E_SERVICE_STOPPED. Also removes a potential problem in holding the reader_table_lock between calls to apdu_dev_list_start apdu_dev_list_finish. There is no need for this. Instead we bump the pcsc.count. The reader_table_lock strategy should be reviewed; we may be able to remove it. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
178e4eb655
commit
bb8e3996e4
2 changed files with 26 additions and 22 deletions
44
scd/apdu.c
44
scd/apdu.c
|
@ -625,6 +625,7 @@ pcsc_error_string (long err)
|
|||
case 0x001c: s = "card unsupported"; break;
|
||||
case 0x001d: s = "no service"; break;
|
||||
case 0x001e: s = "service stopped"; break;
|
||||
case 0x002e: s = "no readers available"; break;
|
||||
default: s = "unknown PC/SC error code"; break;
|
||||
}
|
||||
return s;
|
||||
|
@ -827,12 +828,16 @@ control_pcsc (int slot, pcsc_dword_t ioctl_code,
|
|||
static int
|
||||
close_pcsc_reader (int slot)
|
||||
{
|
||||
/*log_debug ("%s: count=%d (ctx=%x)\n", __func__, pcsc.count, pcsc.context);*/
|
||||
(void)slot;
|
||||
if (--pcsc.count == 0 && npth_mutex_trylock (&reader_table_lock) == 0)
|
||||
if (!pcsc.count || !--pcsc.count)
|
||||
{
|
||||
int i;
|
||||
|
||||
pcsc_release_context (pcsc.context);
|
||||
/*log_debug ("%s: releasing context\n", __func__);*/
|
||||
npth_mutex_lock (&reader_table_lock);
|
||||
if (pcsc.context)
|
||||
pcsc_release_context (pcsc.context);
|
||||
pcsc.context = 0;
|
||||
for (i = 0; i < MAX_READER; i++)
|
||||
pcsc.rdrname[i] = NULL;
|
||||
|
@ -2008,12 +2013,15 @@ apdu_dev_list_start (const char *portstr, struct dev_list **l_p)
|
|||
char *p = NULL;
|
||||
|
||||
if (!pcsc.context)
|
||||
if (pcsc_init () < 0)
|
||||
{
|
||||
xfree (dl);
|
||||
npth_mutex_unlock (&reader_table_lock);
|
||||
return gpg_error (GPG_ERR_NO_SERVICE);
|
||||
}
|
||||
{
|
||||
/* log_debug ("%s: No context - calling init\n", __func__); */
|
||||
if (pcsc_init () < 0)
|
||||
{
|
||||
xfree (dl);
|
||||
npth_mutex_unlock (&reader_table_lock);
|
||||
return gpg_error (GPG_ERR_NO_SERVICE);
|
||||
}
|
||||
}
|
||||
|
||||
r = pcsc_list_readers (pcsc.context, NULL, NULL, &nreader);
|
||||
if (!r)
|
||||
|
@ -2024,9 +2032,9 @@ apdu_dev_list_start (const char *portstr, struct dev_list **l_p)
|
|||
err = gpg_error_from_syserror ();
|
||||
|
||||
log_error ("error allocating memory for reader list\n");
|
||||
npth_mutex_unlock (&reader_table_lock);
|
||||
close_pcsc_reader (0);
|
||||
xfree (dl);
|
||||
npth_mutex_unlock (&reader_table_lock);
|
||||
return err;
|
||||
}
|
||||
r = pcsc_list_readers (pcsc.context, NULL, p, &nreader);
|
||||
|
@ -2036,9 +2044,9 @@ apdu_dev_list_start (const char *portstr, struct dev_list **l_p)
|
|||
log_error ("pcsc_list_readers failed: %s (0x%lx)\n",
|
||||
pcsc_error_string (r), r);
|
||||
xfree (p);
|
||||
npth_mutex_unlock (&reader_table_lock);
|
||||
close_pcsc_reader (0);
|
||||
xfree (dl);
|
||||
npth_mutex_unlock (&reader_table_lock);
|
||||
return iso7816_map_sw (pcsc_error_to_sw (r));
|
||||
}
|
||||
|
||||
|
@ -2074,8 +2082,12 @@ apdu_dev_list_start (const char *portstr, struct dev_list **l_p)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pcsc.count++;
|
||||
}
|
||||
|
||||
npth_mutex_unlock (&reader_table_lock);
|
||||
|
||||
*l_p = dl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2092,20 +2104,10 @@ apdu_dev_list_finish (struct dev_list *dl)
|
|||
else
|
||||
#endif
|
||||
{ /* PC/SC readers. */
|
||||
int i;
|
||||
|
||||
xfree (dl->table);
|
||||
for (i = 0; i < MAX_READER; i++)
|
||||
pcsc.rdrname[i] = NULL;
|
||||
|
||||
if (pcsc.count == 0)
|
||||
{
|
||||
pcsc_release_context (pcsc.context);
|
||||
pcsc.context = 0;
|
||||
}
|
||||
close_pcsc_reader (0);
|
||||
}
|
||||
xfree (dl);
|
||||
npth_mutex_unlock (&reader_table_lock);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue