Skip to content

Commit

Permalink
PCSCCardRequest: use a local PC/SC context to avoid locks
Browse files Browse the repository at this point in the history
SCardGetStatusChange() should not be called from the same PC/SC context
used by all the other PC/SC functions. Because of a mutex in pcsc-lite
the calls using the same context are exclusive. So the performances were
bad.

The problem was discovered by the framework testsuite that was running
very slow on GNU/Linux (but not on Windows or macOS).
  • Loading branch information
LudovicRousseau committed Oct 19, 2024
1 parent 160d0bd commit d9c0bf9
Showing 1 changed file with 22 additions and 7 deletions.
29 changes: 22 additions & 7 deletions src/smartcard/pcsc/PCSCCardRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
CardRequestTimeoutException,
ListReadersException,
)
from smartcard.pcsc.PCSCContext import PCSCContext
from smartcard.pcsc.PCSCExceptions import (
EstablishContextException,
ReleaseContextException,
)
from smartcard.pcsc.PCSCReader import PCSCReader
from smartcard.scard import *

Expand Down Expand Up @@ -79,24 +82,36 @@ def __init__(
else:
self.timeout = int(self.timeout * 1000)

self.hcontext = PCSCContext().getContext()
hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
raise EstablishContextException(hresult)
self.evt = threading.Event()
self.hresult = SCARD_S_SUCCESS
self.readerstates = {}
self.newstates = []
self.timeout_init = self.timeout

def __del__(self):
hresult = SCardReleaseContext(self.hcontext)
if hresult != SCARD_S_SUCCESS:
raise ReleaseContextException(hresult)
self.hcontext = -1

def getReaderNames(self):
"""Returns the list of PCSC readers on which to wait for cards."""

# renew the context in case PC/SC was stopped
# this happens on Windows when the last reader is disconnected
self.hcontext = PCSCContext().getContext()

# get inserted readers
hresult, pcscreaders = SCardListReaders(self.hcontext, [])

# renew the context in case PC/SC was stopped
# this happens on Windows when the last reader is disconnected
if hresult in (SCARD_E_SERVICE_STOPPED, SCARD_E_NO_SERVICE):
self.hcontext = PCSCContext().renewContext()
hresult = SCardReleaseContext(self.hcontext)
if hresult != SCARD_S_SUCCESS:
raise ReleaseContextException(hresult)
hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
raise EstablishContextException(hresult)
hresult, pcscreaders = SCardListReaders(self.hcontext, [])
if SCARD_E_NO_READERS_AVAILABLE == hresult:
return []
Expand Down

0 comments on commit d9c0bf9

Please sign in to comment.