aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2021-05-13 01:45:52 +0000
committerNIIBE Yutaka <[email protected]>2021-05-13 01:45:52 +0000
commit8fc75864bdedecc8ee8730d3ca91ec5acff39f63 (patch)
treef5ab25c088ab804c19e8d2a8d5f1934673e9caab
parentscd: Protect PCSC.CONTEXT in apdu_dev_list_start. (diff)
downloadgnupg-8fc75864bdedecc8ee8730d3ca91ec5acff39f63.tar.gz
gnupg-8fc75864bdedecc8ee8730d3ca91ec5acff39f63.zip
scd: Add a thread for PS/SC which blocks at SCardGetStatusChange.
* scd/apdu.c (pcsc_thread): New. (pcsc_init): Invoke the thread. -- Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r--scd/apdu.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/scd/apdu.c b/scd/apdu.c
index a081b37f0..7c9c563b4 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -1124,6 +1124,55 @@ pcsc_vendor_specific_init (int slot)
return 0;
}
+
+#define STATUS_CHANGE_TIMEOUT 2500
+
+static void *
+pcsc_thread (void *arg)
+{
+ long err;
+ struct pcsc_readerstate_s rdrstates[MAX_READER];
+
+ (void)arg;
+
+ npth_mutex_lock (&reader_table_lock);
+ while (pcsc.count)
+ {
+ int i, j = 0;
+
+ pcsc.count++;
+ memset (rdrstates, 0, sizeof *rdrstates);
+
+ for (i = 0; i < MAX_READER; i++)
+ if (reader_table[i].used)
+ {
+ rdrstates[j].reader = reader_table[i].rdrname;
+ rdrstates[j].current_state = reader_table[i].pcsc.current_state;
+ j++;
+ }
+ npth_mutex_unlock (&reader_table_lock);
+
+#ifdef USE_NPTH
+ npth_unprotect ();
+#endif
+ err = pcsc_get_status_change (pcsc.context, STATUS_CHANGE_TIMEOUT,
+ rdrstates, j);
+#ifdef USE_NPTH
+ npth_protect ();
+#endif
+
+ npth_mutex_lock (&reader_table_lock);
+
+ log_assert (pcsc.count > 0);
+ if (!--pcsc.count)
+ release_pcsc_context ();
+ }
+
+ npth_mutex_unlock (&reader_table_lock);
+ return NULL;
+}
+
+
static int
pcsc_init (void)
{
@@ -1223,6 +1272,29 @@ pcsc_init (void)
pcsc_error_string (err), err);
return -1;
}
+ else
+ {
+ npth_t thread;
+ npth_attr_t tattr;
+ int err_npth;
+
+ err_npth = npth_attr_init (&tattr);
+ if (err_npth)
+ {
+ log_error ("npth_attr_init failed: %s\n", strerror (err_npth));
+ return -1;
+ }
+
+ npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
+ err_npth = npth_create (&thread, &tattr, pcsc_thread, NULL);
+ if (err_npth)
+ {
+ log_error ("npth_create failed: %s\n", strerror (err_npth));
+ return -1;
+ }
+
+ npth_attr_destroy (&tattr);
+ }
return 0;
}