Skip to content

Instantly share code, notes, and snippets.

@FiloSottile
Last active October 17, 2015 21:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FiloSottile/2cf4eb826d66b765e312 to your computer and use it in GitHub Desktop.
Save FiloSottile/2cf4eb826d66b765e312 to your computer and use it in GitHub Desktop.
Tested on GnuPG 2.1.9. Fixes hang when using gpg-agent with YubiKeys on OS X. Port of https://github.com/GPGTools/MacGPG2/blob/6b5a3c/Formula/Patches/gnupg2/pcsc-wrapper.patch
--- a/scd/apdu.c 2015-10-17 22:25:39.000000000 +0100
+++ b/scd/apdu.c 2015-10-17 22:29:52.000000000 +0100
@@ -29,6 +29,7 @@
#include <string.h>
#include <assert.h>
#include <signal.h>
+#include <pthread.h>
#ifdef USE_NPTH
# include <unistd.h>
# include <fcntl.h>
@@ -944,6 +945,23 @@
#ifndef NEED_PCSC_WRAPPER
+struct myArgs {
+ long pcsc_context;
+ struct pcsc_readerstate_s *rdrstates;
+ pthread_cond_t cond;
+ long err;
+};
+
+// Helper Thread to have a timeout for pcsc_get_status_change.
+void *get_status_change_thread (void *pointer) {
+ struct myArgs *args = pointer;
+ args->err = pcsc_get_status_change (args->pcsc_context,
+ 0,
+ args->rdrstates, 1);
+ pthread_cond_signal(&args->cond);
+ return NULL;
+}
+
static int
pcsc_get_status_direct (int slot, unsigned int *status)
{
@@ -953,9 +971,32 @@
memset (rdrstates, 0, sizeof *rdrstates);
rdrstates[0].reader = reader_table[slot].rdrname;
rdrstates[0].current_state = PCSC_STATE_UNAWARE;
- err = pcsc_get_status_change (reader_table[slot].pcsc.context,
- 0,
- rdrstates, 1);
+
+ pthread_t thread;
+ struct myArgs args;
+ args.rdrstates = rdrstates;
+ args.pcsc_context = reader_table[slot].pcsc.context;
+
+ pthread_cond_init(&args.cond, NULL);
+ pthread_create(&thread, NULL, get_status_change_thread, &args);
+
+ static struct timespec time_to_wait = {0, 0};
+ time_to_wait.tv_sec = time(NULL) + 5;
+
+ pthread_mutex_t lock;
+ pthread_mutex_init(&lock, NULL);
+ pthread_mutex_lock(&lock);
+ err = pthread_cond_timedwait(&args.cond, &lock, &time_to_wait);
+ pthread_mutex_unlock(&lock);
+
+ if (err) {
+ pthread_cancel(thread);
+ err = PCSC_E_TIMEOUT;
+ } else {
+ pthread_join(thread, NULL);
+ err = args.err;
+ }
+
if (err == PCSC_E_TIMEOUT)
err = 0; /* Timeout is no error error here. */
if (err)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment