From 6ae2e4003cda4cd06803ceb418a054c220be3254 Mon Sep 17 00:00:00 2001 From: bicarus-dev <202771338+bicarus-dev@users.noreply.github.com> Date: Mon, 15 Dec 2025 20:55:14 -0800 Subject: [PATCH] scard: stop polling if scard service dies (#451) ## Link to GitHub Issue, if one exists n/a ## Description of change If `SCardGetStatusChange` returns `SCARD_E_SERVICE_STOPPED`, stop polling. Add some sleep if it fails for other reasons to prevent busy loops. ## Testing Tested with ACR122U reader. --- src/spice2x/external/scard/scard.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/spice2x/external/scard/scard.cpp b/src/spice2x/external/scard/scard.cpp index 5f66190..ac5c599 100644 --- a/src/spice2x/external/scard/scard.cpp +++ b/src/spice2x/external/scard/scard.cpp @@ -270,6 +270,21 @@ void scard_loop(SCARDCONTEXT hContext, LPCTSTR slot0_reader_name, LPCTSTR slot1_ continue; } else if (lRet != SCARD_S_SUCCESS) { log_warning("scard", "failed SCardGetStatusChange: 0x{:08x}", static_cast(lRet)); + + // scard service disappeared, probably because the last reader was unplugged + // we currently can't recover from this; we would need to rediscover reader devices + // using SCardListReaders + if (lRet == SCARD_E_SERVICE_STOPPED) { + log_warning( + "scard", + "scard service stopped, polling will stop; " + "the smart card reader was likely unplugged"); + break; + } + + // SCardGetStatusChange can return immediately on some error states; + // wait a bit to prevent excessive polling + Sleep(SCARD_POLL_INTERVAL_MS * 10); continue; } @@ -399,6 +414,7 @@ int scard_threadmain() { if (reader_name_slots[1]) { HeapFree(GetProcessHeap(), 0, reader_name_slots[1]); } + log_misc("scard", "exiting main thread"); return 0; }