SCardGetStatusChange() blocks forever after some time
SCardGetStatusChange() does not work correctly on Mac OS X 10.10 Yosemite. Sometimes the function blocks and does not return.The execution do not always block at the same iteration. It looks like an internal dead lock in some circumstances.
See also
The problem was reported to me by Paolo S. Thanks to him.Apple bug report #21437286 "PC/SC SCardGetStatusChange() blocks forever after some time".
Closed by Apple on 27th June 2015, as duplicate of #20517200.
Sample code
Code from Paolo S.#include <stdio.h> #include <stdlib.h> #ifdef __APPLE__ #include <PCSC/winscard.h> #include <PCSC/wintypes.h> #else #include <winscard.h> #endif #define CHECK(f, rv) \ if (SCARD_S_SUCCESS != rv) \ { \ printf(f ": %s\n", pcsc_stringify_error(rv)); \ return -1; \ } int main(void) { LONG rv; SCARDCONTEXT hContext; LPTSTR mszReaders; DWORD dwReaders; unsigned int i; rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); CHECK("SCardEstablishContext", rv) rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); CHECK("SCardListReaders", rv) mszReaders = calloc(dwReaders, sizeof(char)); rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders); CHECK("SCardListReaders", rv) if (dwReaders <= 1) { puts("No reader found"); goto end ; } printf("reader name: %s\n", mszReaders); SCARD_READERSTATE sReaderState ; sReaderState.szReader = mszReaders ; i = 0 ; while(1) { i++ ; printf("Loop #%d: calling SCardGetStatusChange\n", i); rv = SCardGetStatusChange(hContext, 1, &sReaderState, 1); // This hangs after random number of calls puts("returned"); CHECK("SCardGetStatusChange", rv) } free(mszReaders); end: rv = SCardReleaseContext(hContext); CHECK("SCardReleaseContext", rv) return 0; }
Result (on Yosemite)
$ ./main reader name: Gemalto PC Twin Reader Loop #1: calling SCardGetStatusChange returned Loop #2: calling SCardGetStatusChange [...] Loop #11145: calling SCardGetStatusChange returned Loop #11146: calling SCardGetStatusChange ^C
I have to use Control-C to stop the execution.
Known workaround
Paolo S. has a workaround.- detect the card presence by calling the SCardConnect() function (shared mode, default protocols). no errors = card inserted.
- detect the card extraction by calling the SCardReconnect() function (same parameters, no card reset or eject). no errors = card still inserted.