mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
scd: Modify DEVINFO behavior to support looping forever.
* scd/app.c (struct mrsw_lock): Add notify_cond member. (notify_cond): Remove. (card_list_r_lock, card_list_r_unlock): Rename. (card_list_w_lock, card_list_w_unlock): Rename. (card_list_signal, card_list_wait): New, fixing thinko about notify/wakeup with MRSW lock. (app_send_devinfo): Support looping. (select_application): Notify app_send_devinfo thread for newly detected device. (initialize_module_command): Initialize notify_cond member. (app_wait): Remove. * scd/command.c (cmd_devinfo): Use new API of app_send_devinfo. * scd/scdaemon.h (app_wait): Remove. -- GnuPG-bug-id: 5359 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
50e43af3f1
commit
48e824b6ea
168
scd/app.c
168
scd/app.c
@ -49,11 +49,9 @@ struct mrsw_lock
|
|||||||
int num_readers_active;
|
int num_readers_active;
|
||||||
int num_writers_waiting;
|
int num_writers_waiting;
|
||||||
int writer_active;
|
int writer_active;
|
||||||
|
npth_cond_t notify_cond;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CARD_LIST_LOCK_WAIT 0
|
|
||||||
#define CARD_LIST_LOCK_UPDATE 1
|
|
||||||
|
|
||||||
/* MRSW lock to protect the list of cards.
|
/* MRSW lock to protect the list of cards.
|
||||||
*
|
*
|
||||||
* This structure is used for serializing access to the list of cards
|
* This structure is used for serializing access to the list of cards
|
||||||
@ -63,10 +61,9 @@ struct mrsw_lock
|
|||||||
*
|
*
|
||||||
* Each use of a CARD (in the list) does "r" access.
|
* Each use of a CARD (in the list) does "r" access.
|
||||||
*
|
*
|
||||||
* For "w" access, the app_wait function, which waits on any change of
|
* For "w" access, the app_send_devinfo function may wait on any
|
||||||
* the list, it uses CARD_LIST_LOCK_WAIT. For other cases of "w"
|
* change of the list. For other cases of "w" access are opening new
|
||||||
* access (opening new card or removal of card), CARD_LIST_LOCK_UPDATE
|
* card or removal of card, updating the list of card.
|
||||||
* is used.
|
|
||||||
*
|
*
|
||||||
* Note that for serializing access to each CARD (and its associated
|
* Note that for serializing access to each CARD (and its associated
|
||||||
* applications) itself, it is done separately by another mutex with
|
* applications) itself, it is done separately by another mutex with
|
||||||
@ -74,9 +71,6 @@ struct mrsw_lock
|
|||||||
*/
|
*/
|
||||||
static struct mrsw_lock card_list_lock;
|
static struct mrsw_lock card_list_lock;
|
||||||
|
|
||||||
/* Notification to threads which keep watching the status change. */
|
|
||||||
static npth_cond_t notify_cond;
|
|
||||||
|
|
||||||
/* A list of card contexts. A card is a collection of applications
|
/* A list of card contexts. A card is a collection of applications
|
||||||
* (described by app_t) on the same physical token. */
|
* (described by app_t) on the same physical token. */
|
||||||
static card_t card_top;
|
static card_t card_top;
|
||||||
@ -325,7 +319,7 @@ unlock_card (card_t card)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lock_r_card_list (void)
|
card_list_r_lock (void)
|
||||||
{
|
{
|
||||||
npth_mutex_lock (&card_list_lock.lock);
|
npth_mutex_lock (&card_list_lock.lock);
|
||||||
while (card_list_lock.num_writers_waiting
|
while (card_list_lock.num_writers_waiting
|
||||||
@ -336,7 +330,7 @@ lock_r_card_list (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unlock_r_card_list (void)
|
card_list_r_unlock (void)
|
||||||
{
|
{
|
||||||
npth_mutex_lock (&card_list_lock.lock);
|
npth_mutex_lock (&card_list_lock.lock);
|
||||||
if (--card_list_lock.num_readers_active == 0)
|
if (--card_list_lock.num_readers_active == 0)
|
||||||
@ -346,7 +340,7 @@ unlock_r_card_list (void)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lock_w_card_list (int for_update)
|
card_list_w_lock (void)
|
||||||
{
|
{
|
||||||
npth_mutex_lock (&card_list_lock.lock);
|
npth_mutex_lock (&card_list_lock.lock);
|
||||||
card_list_lock.num_writers_waiting++;
|
card_list_lock.num_writers_waiting++;
|
||||||
@ -354,26 +348,46 @@ lock_w_card_list (int for_update)
|
|||||||
|| card_list_lock.writer_active)
|
|| card_list_lock.writer_active)
|
||||||
npth_cond_wait (&card_list_lock.cond, &card_list_lock.lock);
|
npth_cond_wait (&card_list_lock.cond, &card_list_lock.lock);
|
||||||
card_list_lock.num_writers_waiting--;
|
card_list_lock.num_writers_waiting--;
|
||||||
if (for_update)
|
card_list_lock.writer_active++;
|
||||||
{
|
npth_mutex_unlock (&card_list_lock.lock);
|
||||||
card_list_lock.writer_active++;
|
|
||||||
npth_mutex_unlock (&card_list_lock.lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unlock_w_card_list (int for_update)
|
card_list_w_unlock (void)
|
||||||
{
|
{
|
||||||
if (for_update)
|
npth_mutex_lock (&card_list_lock.lock);
|
||||||
{
|
card_list_lock.writer_active--;
|
||||||
npth_mutex_lock (&card_list_lock.lock);
|
|
||||||
card_list_lock.writer_active--;
|
|
||||||
}
|
|
||||||
npth_cond_broadcast (&card_list_lock.cond);
|
npth_cond_broadcast (&card_list_lock.cond);
|
||||||
npth_mutex_unlock (&card_list_lock.lock);
|
npth_mutex_unlock (&card_list_lock.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
card_list_signal (void)
|
||||||
|
{
|
||||||
|
npth_cond_broadcast (&card_list_lock.notify_cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
card_list_wait (void)
|
||||||
|
{
|
||||||
|
npth_mutex_lock (&card_list_lock.lock);
|
||||||
|
card_list_lock.writer_active--;
|
||||||
|
npth_cond_broadcast (&card_list_lock.cond);
|
||||||
|
|
||||||
|
npth_cond_wait (&card_list_lock.notify_cond, &card_list_lock.lock);
|
||||||
|
|
||||||
|
card_list_lock.num_writers_waiting++;
|
||||||
|
while (card_list_lock.num_readers_active
|
||||||
|
|| card_list_lock.writer_active)
|
||||||
|
npth_cond_wait (&card_list_lock.cond, &card_list_lock.lock);
|
||||||
|
card_list_lock.num_writers_waiting--;
|
||||||
|
|
||||||
|
card_list_lock.writer_active++;
|
||||||
|
npth_mutex_unlock (&card_list_lock.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function may be called to print information pertaining to the
|
/* This function may be called to print information pertaining to the
|
||||||
* current state of this module to the log. */
|
* current state of this module to the log. */
|
||||||
void
|
void
|
||||||
@ -382,7 +396,7 @@ app_dump_state (void)
|
|||||||
card_t c;
|
card_t c;
|
||||||
app_t a;
|
app_t a;
|
||||||
|
|
||||||
lock_r_card_list ();
|
card_list_r_lock ();
|
||||||
for (c = card_top; c; c = c->next)
|
for (c = card_top; c; c = c->next)
|
||||||
{
|
{
|
||||||
log_info ("app_dump_state: card=%p slot=%d type=%s refcount=%u\n",
|
log_info ("app_dump_state: card=%p slot=%d type=%s refcount=%u\n",
|
||||||
@ -392,37 +406,59 @@ app_dump_state (void)
|
|||||||
log_info ("app_dump_state: app=%p type='%s'\n",
|
log_info ("app_dump_state: app=%p type='%s'\n",
|
||||||
a, strapptype (a->apptype));
|
a, strapptype (a->apptype));
|
||||||
}
|
}
|
||||||
unlock_r_card_list ();
|
card_list_r_unlock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send information for all available cards.
|
||||||
|
*
|
||||||
|
* With KEEP_LOOPING=0, it only outputs once.
|
||||||
|
* With KEEP_LOOPING<0, it keeps looping, until it detects no device.
|
||||||
|
* With KEEP_LOOPING>0, it keeps looping forever.
|
||||||
|
*/
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
app_send_devinfo (ctrl_t ctrl)
|
app_send_devinfo (ctrl_t ctrl, int keep_looping)
|
||||||
{
|
{
|
||||||
card_t c;
|
card_t c;
|
||||||
app_t a;
|
app_t a;
|
||||||
int no_device;
|
int no_device;
|
||||||
|
|
||||||
send_status_direct (ctrl, "DEVINFO_START", "");
|
while (1)
|
||||||
|
|
||||||
lock_r_card_list ();
|
|
||||||
no_device = (card_top == NULL);
|
|
||||||
for (c = card_top; c; c = c->next)
|
|
||||||
{
|
{
|
||||||
char *serialno;
|
card_list_w_lock ();
|
||||||
char card_info[80];
|
|
||||||
|
|
||||||
serialno = card_get_serialno (c);
|
no_device = (card_top == NULL);
|
||||||
snprintf (card_info, sizeof card_info, "DEVICE %s %s",
|
if (no_device && keep_looping < 0)
|
||||||
strcardtype (c->cardtype), serialno);
|
{
|
||||||
xfree (serialno);
|
card_list_w_unlock ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (a = c->app; a; a = a->next)
|
send_status_direct (ctrl, "DEVINFO_START", "");
|
||||||
send_status_direct (ctrl, card_info, strapptype (a->apptype));
|
for (c = card_top; c; c = c->next)
|
||||||
|
{
|
||||||
|
char *serialno;
|
||||||
|
char card_info[80];
|
||||||
|
|
||||||
|
serialno = card_get_serialno (c);
|
||||||
|
snprintf (card_info, sizeof card_info, "DEVICE %s %s",
|
||||||
|
strcardtype (c->cardtype), serialno);
|
||||||
|
xfree (serialno);
|
||||||
|
|
||||||
|
for (a = c->app; a; a = a->next)
|
||||||
|
send_status_direct (ctrl, card_info, strapptype (a->apptype));
|
||||||
|
}
|
||||||
|
send_status_direct (ctrl, "DEVINFO_END", "");
|
||||||
|
|
||||||
|
if (no_device && !keep_looping)
|
||||||
|
{
|
||||||
|
card_list_w_unlock ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
card_list_wait ();
|
||||||
|
card_list_w_unlock ();
|
||||||
}
|
}
|
||||||
unlock_r_card_list ();
|
|
||||||
|
|
||||||
send_status_direct (ctrl, "DEVINFO_END", "");
|
|
||||||
|
|
||||||
return no_device ? gpg_error (GPG_ERR_NOT_FOUND): 0;
|
return no_device ? gpg_error (GPG_ERR_NOT_FOUND): 0;
|
||||||
}
|
}
|
||||||
@ -774,7 +810,7 @@ select_application (ctrl_t ctrl, const char *name,
|
|||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
card_t card, card_prev = NULL;
|
card_t card, card_prev = NULL;
|
||||||
|
|
||||||
lock_w_card_list (CARD_LIST_LOCK_UPDATE);
|
card_list_w_lock ();
|
||||||
|
|
||||||
ctrl->card_ctx = NULL;
|
ctrl->card_ctx = NULL;
|
||||||
|
|
||||||
@ -787,7 +823,7 @@ select_application (ctrl_t ctrl, const char *name,
|
|||||||
err = apdu_dev_list_start (opt.reader_port, &l);
|
err = apdu_dev_list_start (opt.reader_port, &l);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
unlock_w_card_list (CARD_LIST_LOCK_UPDATE);
|
card_list_w_unlock ();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -824,7 +860,11 @@ select_application (ctrl_t ctrl, const char *name,
|
|||||||
|
|
||||||
/* If new device(s), kick the scdaemon loop. */
|
/* If new device(s), kick the scdaemon loop. */
|
||||||
if (new_card)
|
if (new_card)
|
||||||
scd_kick_the_loop ();
|
{
|
||||||
|
scd_kick_the_loop ();
|
||||||
|
/* Also notify watching by DEVINFO */
|
||||||
|
card_list_signal ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (card = card_top; card; card = card->next)
|
for (card = card_top; card; card = card->next)
|
||||||
@ -874,7 +914,7 @@ select_application (ctrl_t ctrl, const char *name,
|
|||||||
else
|
else
|
||||||
err = gpg_error (GPG_ERR_ENODEV);
|
err = gpg_error (GPG_ERR_ENODEV);
|
||||||
|
|
||||||
unlock_w_card_list (CARD_LIST_LOCK_UPDATE);
|
card_list_w_unlock ();
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -890,7 +930,7 @@ app_switch_current_card (ctrl_t ctrl,
|
|||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
card_t card, cardtmp;
|
card_t card, cardtmp;
|
||||||
|
|
||||||
lock_r_card_list ();
|
card_list_r_lock ();
|
||||||
|
|
||||||
cardtmp = ctrl->card_ctx;
|
cardtmp = ctrl->card_ctx;
|
||||||
if (!cardtmp)
|
if (!cardtmp)
|
||||||
@ -926,7 +966,7 @@ app_switch_current_card (ctrl_t ctrl,
|
|||||||
err = send_serialno_and_app_status (ctrl->card_ctx, 0, ctrl);
|
err = send_serialno_and_app_status (ctrl->card_ctx, 0, ctrl);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
unlock_r_card_list ();
|
card_list_r_unlock ();
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1244,14 +1284,14 @@ card_get (ctrl_t ctrl, const char *keygrip)
|
|||||||
{
|
{
|
||||||
card_t card;
|
card_t card;
|
||||||
|
|
||||||
lock_r_card_list ();
|
card_list_r_lock ();
|
||||||
if (keygrip)
|
if (keygrip)
|
||||||
card = do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keygrip, 0);
|
card = do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, keygrip, 0);
|
||||||
else
|
else
|
||||||
card = ctrl->card_ctx;
|
card = ctrl->card_ctx;
|
||||||
if (!card)
|
if (!card)
|
||||||
{
|
{
|
||||||
unlock_r_card_list ();
|
card_list_r_unlock ();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1268,7 +1308,7 @@ card_put (card_t card)
|
|||||||
is using the card - this way the PIN cache and other cached data
|
is using the card - this way the PIN cache and other cached data
|
||||||
are preserved. */
|
are preserved. */
|
||||||
unlock_card (card);
|
unlock_card (card);
|
||||||
unlock_r_card_list ();
|
card_list_r_unlock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2348,7 +2388,7 @@ scd_update_reader_status_file (void)
|
|||||||
int periodical_check_needed = 0;
|
int periodical_check_needed = 0;
|
||||||
int reported = 0;
|
int reported = 0;
|
||||||
|
|
||||||
lock_w_card_list (CARD_LIST_LOCK_UPDATE);
|
card_list_w_lock ();
|
||||||
for (card = card_top; card; card = card_next)
|
for (card = card_top; card; card = card_next)
|
||||||
{
|
{
|
||||||
int sw;
|
int sw;
|
||||||
@ -2412,9 +2452,9 @@ scd_update_reader_status_file (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reported)
|
if (reported)
|
||||||
npth_cond_broadcast (¬ify_cond);
|
card_list_signal ();
|
||||||
|
|
||||||
unlock_w_card_list (CARD_LIST_LOCK_UPDATE);
|
card_list_w_unlock ();
|
||||||
|
|
||||||
return periodical_check_needed;
|
return periodical_check_needed;
|
||||||
}
|
}
|
||||||
@ -2447,7 +2487,7 @@ initialize_module_command (void)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = npth_cond_init (¬ify_cond, NULL);
|
err = npth_cond_init (&card_list_lock.notify_cond, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
@ -2542,7 +2582,7 @@ send_card_and_app_list (ctrl_t ctrl, card_t wantcard, int with_apps)
|
|||||||
card_t *cardlist = NULL;
|
card_t *cardlist = NULL;
|
||||||
int n, ncardlist;
|
int n, ncardlist;
|
||||||
|
|
||||||
lock_r_card_list ();
|
card_list_r_lock ();
|
||||||
for (n=0, c = card_top; c; c = c->next)
|
for (n=0, c = card_top; c; c = c->next)
|
||||||
n++;
|
n++;
|
||||||
if (!n)
|
if (!n)
|
||||||
@ -2572,7 +2612,7 @@ send_card_and_app_list (ctrl_t ctrl, card_t wantcard, int with_apps)
|
|||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
unlock_r_card_list ();
|
card_list_r_unlock ();
|
||||||
xfree (cardlist);
|
xfree (cardlist);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -2665,16 +2705,8 @@ app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str,
|
|||||||
{
|
{
|
||||||
card_t card;
|
card_t card;
|
||||||
|
|
||||||
lock_r_card_list ();
|
card_list_r_lock ();
|
||||||
card = do_with_keygrip (ctrl, action, keygrip_str, capability);
|
card = do_with_keygrip (ctrl, action, keygrip_str, capability);
|
||||||
unlock_r_card_list ();
|
card_list_r_unlock ();
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
app_wait (void)
|
|
||||||
{
|
|
||||||
lock_w_card_list (CARD_LIST_LOCK_WAIT);
|
|
||||||
npth_cond_wait (¬ify_cond, &card_list_lock.lock);
|
|
||||||
unlock_w_card_list (CARD_LIST_LOCK_WAIT);
|
|
||||||
}
|
|
||||||
|
@ -2279,7 +2279,7 @@ cmd_devinfo (assuan_context_t ctx, char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Firstly, send information of available devices. */
|
/* Firstly, send information of available devices. */
|
||||||
err = app_send_devinfo (ctrl);
|
err = app_send_devinfo (ctrl, 0);
|
||||||
|
|
||||||
/* If not watching, that's all. */
|
/* If not watching, that's all. */
|
||||||
if (!watch)
|
if (!watch)
|
||||||
@ -2311,16 +2311,10 @@ cmd_devinfo (assuan_context_t ctx, char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Then, keep watching the status change. */
|
/* Then, keep watching the status change. */
|
||||||
while (!err)
|
err = app_send_devinfo (ctrl, 1);
|
||||||
{
|
|
||||||
app_wait ();
|
|
||||||
|
|
||||||
/* Send information of available devices. */
|
|
||||||
err = app_send_devinfo (ctrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrl->server_local->watching_status = 0;
|
ctrl->server_local->watching_status = 0;
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if the command CMD implements the option OPT. */
|
/* Return true if the command CMD implements the option OPT. */
|
||||||
|
@ -155,7 +155,6 @@ int get_active_connection_count (void);
|
|||||||
|
|
||||||
/*-- app.c --*/
|
/*-- app.c --*/
|
||||||
int scd_update_reader_status_file (void);
|
int scd_update_reader_status_file (void);
|
||||||
void app_wait (void);
|
gpg_error_t app_send_devinfo (ctrl_t ctrl, int keep_looping);
|
||||||
gpg_error_t app_send_devinfo (ctrl_t ctrl);
|
|
||||||
|
|
||||||
#endif /*SCDAEMON_H*/
|
#endif /*SCDAEMON_H*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user