[Pcsclite-cvs-commit] r6388 - in /trunk/PCSC/src: readerfactory.c readerfactory.h winscard.c

rousseau at users.alioth.debian.org rousseau at users.alioth.debian.org
Thu Jul 5 14:14:17 UTC 2012


Author: rousseau
Date: Thu Jul  5 14:14:16 2012
New Revision: 6388

URL: http://svn.debian.org/wsvn/pcsclite/?sc=1&rev=6388
Log:
Add a reader reference count to be used as a Garbage Collector

A reader should be removed only when no one is using it, not just when
the reader is unplugged.

An application may be in the middle of using the reader when the reader
is unplugged. If the reader is removed right when unplugged then pcscd
may use a no more existing reader structure and crash.

Thanks to Martin Vogt for the bug report.
http://archives.neohapsis.com/archives/dev/muscle/2012-q2/0041.html

Modified:
    trunk/PCSC/src/readerfactory.c
    trunk/PCSC/src/readerfactory.h
    trunk/PCSC/src/winscard.c

Modified: trunk/PCSC/src/readerfactory.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/readerfactory.c?rev=6388&op=diff
==============================================================================
--- trunk/PCSC/src/readerfactory.c (original)
+++ trunk/PCSC/src/readerfactory.c Thu Jul  5 14:14:16 2012
@@ -58,6 +58,7 @@
 static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
 
 #define IDENTITY_SHIFT 16
+static LONG removeReader(READER_CONTEXT * sReader);
 
 static int RDR_CLIHANDLES_seeker(const void *el, const void *key)
 {
@@ -77,6 +78,33 @@
 	return 0;
 }
 
+
+LONG _RefReader(READER_CONTEXT * sReader)
+{
+	if (0 == sReader->reference)
+		return SCARD_E_READER_UNAVAILABLE;
+
+	pthread_mutex_lock(&sReader->reference_lock);
+	sReader->reference += 1;
+	pthread_mutex_unlock(&sReader->reference_lock);
+
+	return SCARD_S_SUCCESS;
+}
+
+LONG _UnrefReader(READER_CONTEXT * sReader)
+{
+	if (0 == sReader->reference)
+		return SCARD_E_READER_UNAVAILABLE;
+
+	pthread_mutex_lock(&sReader->reference_lock);
+	sReader->reference -= 1;
+	pthread_mutex_unlock(&sReader->reference_lock);
+
+	if (0 == sReader->reference)
+		removeReader(sReader);
+
+	return SCARD_S_SUCCESS;
+}
 
 LONG RFAllocateReaderSpace(unsigned int customMaxReaderHandles)
 {
@@ -217,6 +245,11 @@
 	(void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock,
 		NULL);
 	sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED;
+
+	/* reference count */
+	(void)pthread_mutex_init(&sReadersContexts[dwContext]->reference_lock,
+		NULL);
+	sReadersContexts[dwContext]->reference = 1;
 
 	/* If a clone to this reader exists take some values from that clone */
 	if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS)
@@ -411,6 +444,11 @@
 			NULL);
 		sReadersContexts[dwContextB]->powerState = POWER_STATE_UNPOWERED;
 
+		/* reference count */
+		(void)pthread_mutex_init(&sReadersContexts[dwContextB]->reference_lock,
+			NULL);
+		sReadersContexts[dwContextB]->reference = 1;
+
 		/* Call on the parent driver to see if the slots are thread safe */
 		dwGetSize = sizeof(ucThread);
 		rv = IFDGetCapabilities((sReadersContexts[dwContext]),
@@ -476,6 +514,21 @@
 
 	rv = RFReaderInfoNamePort(port, readerName, &sContext);
 	if (SCARD_S_SUCCESS == rv)
+	{
+		/* first to derefence RFReaderInfoNamePort() */
+		UNREF_READER(sContext)
+
+		/* second to remove the reader */
+		UNREF_READER(sContext)
+	}
+
+	return SCARD_S_SUCCESS;
+}
+
+LONG removeReader(READER_CONTEXT * sContext)
+{
+	LONG rv;
+
 	{
 		/* Try to destroy the thread */
 		if (sContext -> pthThread)
@@ -673,6 +726,9 @@
 			if (strcmp(readerName,
 				sReadersContexts[i]->readerState->readerName) == 0)
 			{
+				/* Increase reference count */
+				REF_READER(sReadersContexts[i])
+
 				*sReader = sReadersContexts[i];
 				return SCARD_S_SUCCESS;
 			}
@@ -704,6 +760,9 @@
 			if ((strncmp(readerName, lpcStripReader, MAX_READERNAME - sizeof(" 00 00")) == 0)
 				&& (port == sReadersContexts[i]->port))
 			{
+				/* Increase reference count */
+				REF_READER(sReadersContexts[i])
+
 				*sReader = sReadersContexts[i];
 				return SCARD_S_SUCCESS;
 			}
@@ -728,6 +787,9 @@
 			(void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
 			if (currentHandle != NULL)
 			{
+				/* Increase reference count */
+				REF_READER(sReadersContexts[i])
+
 				*sReader = sReadersContexts[i];
 				return SCARD_S_SUCCESS;
 			}

Modified: trunk/PCSC/src/readerfactory.h
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/readerfactory.h?rev=6388&op=diff
==============================================================================
--- trunk/PCSC/src/readerfactory.h (original)
+++ trunk/PCSC/src/readerfactory.h Thu Jul  5 14:14:16 2012
@@ -109,6 +109,8 @@
 		int * pMutex;			/**< Number of client to mutex */
 		int powerState;			/**< auto power off state */
 		pthread_mutex_t powerState_lock;	/**< powerState mutex */
+		int reference;			/**< number of users of the structure */
+		pthread_mutex_t reference_lock;	 /**< reference mutex */
 
 		struct pubReaderStatesList *readerState; /**< link to the reader state */
 		/* we can't use READER_STATE * here since eventhandler.h can't be
@@ -116,6 +118,12 @@
 	};
 
 	typedef struct ReaderContext READER_CONTEXT;
+
+	LONG _RefReader(READER_CONTEXT * sReader);
+	LONG _UnrefReader(READER_CONTEXT * sReader);
+
+#define REF_READER(reader) { LONG rv; Log2(PCSC_LOG_CRITICAL, "RefReader() count was: %d", reader->reference); rv = _RefReader(reader); if (rv != SCARD_S_SUCCESS) return rv; }
+#define UNREF_READER(reader) {Log2(PCSC_LOG_CRITICAL, "UnrefReader() count was: %d", reader->reference); _UnrefReader(reader);}
 
 	LONG RFAllocateReaderSpace(unsigned int);
 	LONG RFAddReader(const char *, int, const char *, const char *);

Modified: trunk/PCSC/src/winscard.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard.c?rev=6388&op=diff
==============================================================================
--- trunk/PCSC/src/winscard.c (original)
+++ trunk/PCSC/src/winscard.c Thu Jul  5 14:14:16 2012
@@ -487,6 +487,8 @@
 	rContext->readerState->readerSharing = rContext->contexts;
 
 exit:
+	UNREF_READER(rContext)
+
 	PROFILE_END
 
 	return rv;
@@ -789,6 +791,8 @@
 	rv = SCARD_S_SUCCESS;
 
 exit:
+	UNREF_READER(rContext)
+
 	return rv;
 }
 
@@ -1037,6 +1041,8 @@
 	rv = SCARD_S_SUCCESS;
 
 exit:
+	UNREF_READER(rContext)
+
 	return rv;
 }
 
@@ -1077,6 +1083,8 @@
 	Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
 
 exit:
+	UNREF_READER(rContext)
+
 	return rv;
 }
 
@@ -1211,6 +1219,8 @@
 	Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
 
 exit:
+	UNREF_READER(rContext)
+
 	return rv;
 }
 
@@ -1272,6 +1282,8 @@
 		goto exit;
 
 exit:
+	UNREF_READER(rContext)
+
 	return rv;
 }
 
@@ -1329,6 +1341,8 @@
 			rv = SCARD_E_UNSUPPORTED_FEATURE;
 
 exit:
+	UNREF_READER(rContext)
+
 	return rv;
 }
 
@@ -1403,6 +1417,8 @@
 	}
 
 exit:
+	UNREF_READER(rContext)
+
 	return rv;
 }
 
@@ -1451,6 +1467,8 @@
 			rv = SCARD_E_NOT_TRANSACTED;
 
 exit:
+	UNREF_READER(rContext)
+
 	return rv;
 }
 
@@ -1605,6 +1623,8 @@
 	*pcbRecvLength = dwRxLength;
 
 exit:
+	UNREF_READER(rContext)
+
 	return rv;
 }
 




More information about the Pcsclite-cvs-commit mailing list