Package: pcscd
Version: 1.4.3-1.1
Severity: important
Tags: patch

I am using pcsc with a USB CCID reader.  Every so often it hangs.
The reason is revealed by this backtrace, which was captured
while it was hung:

    #0  0x4012a321 in pthread_setcanceltype () from /lib/tls/libc.so.6
    #1  0x4011a05f in syslog () from /lib/tls/libc.so.6
    #2  0x0804d59e in log_msg (priority=1075286924,
        fmt=0xfffffffc <Address 0xfffffffc out of bounds>) at debuglog.c:74
    #3  0x08050b43 in signal_reload (sig=10) at pcscdaemon.c:603
    #4  <signal handler called>
    #5  0x4006e969 in __libc_sigaction () from /lib/tls/libc.so.6
    #6  0x4006ea52 in sigaction () from /lib/tls/libc.so.6
    #7  0x4011a481 in vsyslog () from /lib/tls/libc.so.6
    #8  0x4011a05f in syslog () from /lib/tls/libc.so.6
    #9  0x0804d59e in log_msg (priority=2, fmt=0x0) at debuglog.c:74
    #10 0x0804e4c9 in EHStatusHandlerThread (rContext=0x80e8008) at
    eventhandler.c:301
    #11 0x4002fb63 in start_thread () from /lib/tls/libpthread.so.0
    #12 0x4011e18a in clone () from /lib/tls/libc.so.6

The other thread was also hung in syslog().  Notice what has
happened here.  syslog() was called within another call to
syslog() - something I imagine syslog() doesn't expect.  The
underlying reason is how hotplug events are being handled.
They are being processed by a signal() handler, which can
happen at any time.

The attached patch fixes the problem by forcing hotplug reload
events to be handled synchronously.  Unfortunately it probably
isn't acceptable in its current form as it is very Unix dependant,
and pcscd is obviously meant to be multi-platform.  To make it
multi-platform it would have to be a polling loop which is
something I dislike, or your would have to abstract
pthread_cond_wait in your thread_*.c libraries.


-- System Information:
Debian Release: 3.1
Architecture: i386 (i686)
Kernel: Linux 2.6.17-8.1-lube-686-smp
Locale: LANG=en_AU, LC_CTYPE=en_AU (charmap=ISO-8859-1)

Versions of packages pcscd depends on:
ii  libasedrive-usb [pcsc 2.2-1              PC/SC driver for the Athena ASEDri
ii  libc6                 2.3.2.ds1-22sarge6 GNU C Library: Shared libraries an
ii  libccid [pcsc-ifd-han 1.3.0-2.1          PC/SC driver for USB CCID smart ca
ii  libtowitoko2 [pcsc-if 2.0.7-3            Towitoko smartcard reader PCSC and
ii  libusb-0.1-4          2:0.1.12-2.1       userspace USB programming library
ii  lsb-base              3.0-11             Linux Standard Base 3.0 init scrip

-- no debconf information
diff -Nur pcsc-lite-1.4.3/src/hotplug_libusb.c pcsc-lite-1.4.3-new/src/hotplug_libusb.c
--- pcsc-lite-1.4.3/src/hotplug_libusb.c	2007-06-25 12:24:37.581244425 +1000
+++ pcsc-lite-1.4.3-new/src/hotplug_libusb.c	2007-06-25 12:27:20.222429918 +1000
@@ -56,6 +56,7 @@
 static PCSCLITE_THREAD_T usbNotifyThread;
 static int driverSize = -1;
 static char AraKiriHotPlug = FALSE;
+static int rescan_pipe[2] = { -1, -1 };
 extern int HPForceReaderPolling;
 
 /* values of ifdCapabilities bits */
@@ -380,6 +381,7 @@
 void HPEstablishUSBNotifications(void)
 {
 	int i, do_polling;
+	char dummy;
 
 	/* libusb default is /dev/bus/usb but the devices are not yet visible there
 	 * when a hotplug is requested */
@@ -411,10 +413,26 @@
 		do_polling = TRUE;
 	}
 
-	while (do_polling)
+	if (do_polling)
 	{
-		SYS_Sleep(HPForceReaderPolling);
-		HPRescanUsbBus();
+		while (!AraKiriHotPlug)
+		{
+			SYS_Sleep(HPForceReaderPolling);
+			HPRescanUsbBus();
+		}
+	}
+	else
+	{
+	  	pipe(rescan_pipe);
+		while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0)
+		{
+			Log1(PCSC_LOG_INFO, "Reload serial configuration");
+			HPRescanUsbBus();
+			RFReCheckReaderConf();
+			Log1(PCSC_LOG_INFO, "End reload serial configuration");
+		}
+		close(rescan_pipe[0]);
+		rescan_pipe[0] = -1;
 	}
 }
 
@@ -439,6 +457,11 @@
 LONG HPStopHotPluggables(void)
 {
 	AraKiriHotPlug = TRUE;
+	if (rescan_pipe[1] >= 0)
+	{
+	  	close(rescan_pipe);
+		rescan_pipe[1] = -1;
+	}
 
 	return 0;
 }
@@ -535,8 +558,13 @@
 
 void HPReCheckSerialReaders(void)
 {
-	HPRescanUsbBus();
-	RFReCheckReaderConf();
+  	char dummy;
+
+  	if (rescan_pipe[1] >= 0)
+	{
+		dummy = 0;
+		write(rescan_pipe[1], &dummy, sizeof(dummy));
+	}
 }
 
 #endif
diff -Nur pcsc-lite-1.4.3/src/pcscdaemon.c pcsc-lite-1.4.3-new/src/pcscdaemon.c
--- pcsc-lite-1.4.3/src/pcscdaemon.c	2007-06-25 11:41:29.845060776 +1000
+++ pcsc-lite-1.4.3-new/src/pcscdaemon.c	2007-06-25 12:25:25.093995305 +1000
@@ -558,24 +558,10 @@
 
 void signal_reload(int sig)
 {
-	static int rescan_ongoing = FALSE;
-
 	if (AraKiri)
 		return;
 
-	Log1(PCSC_LOG_INFO, "Reload serial configuration");
-	if (rescan_ongoing)
-	{
-		Log1(PCSC_LOG_INFO, "Rescan already ongoing");
-		return;
-	}
-
-	rescan_ongoing = TRUE;
-
 	HPReCheckSerialReaders();
-
-	rescan_ongoing = FALSE;
-	Log1(PCSC_LOG_INFO, "End reload serial configuration");
 } /* signal_reload */
 
 void signal_trap(int sig)

Reply via email to