Skip to content

Commit

Permalink
libredirect: make init thread safe
Browse files Browse the repository at this point in the history
Use pthread_once() to correctly initialize the library.

The problem was found using the PySCard test suite in parallel.
$ pytest --parallel-threads=2 --iterations=1  test/test_PCSC.py
============================= test session starts ==============================
platform linux -- Python 3.13.1, pytest-8.3.4, pluggy-1.5.0
Using --randomly-seed=3545276201
rootdir: /home/rousseau/Documents/sc/pyscard
configfile: pyproject.toml
plugins: run-parallel-0.3.0, randomly-3.16.0
collected 1 item

test/test_PCSC.py F [100%]

=================================== FAILURES ===================================
________________________________ test_low_level ________________________________

    def test_low_level():
        hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
>       assert hresult in (SCARD_S_SUCCESS, SCARD_E_NO_SERVICE)
E       assert 2148532225 in (0, 2148532253)

test/test_PCSC.py:6: AssertionError
=============================== warnings summary ===============================
<frozen importlib._bootstrap>:488
  <frozen importlib._bootstrap>:488: DeprecationWarning: builtin type SwigPyPacked has no __module__ attribute

<frozen importlib._bootstrap>:488
  <frozen importlib._bootstrap>:488: DeprecationWarning: builtin type SwigPyObject has no __module__ attribute

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED test/test_PCSC.py::test_low_level - assert 2148532225 in (0, 2148532253)
======================== 1 failed, 2 warnings in 0.04s =========================
<sys>:0: DeprecationWarning: builtin type swigvarlink has no __module__ attribute
  • Loading branch information
LudovicRousseau committed Feb 4, 2025
1 parent efe2458 commit f0f4fa1
Showing 1 changed file with 6 additions and 18 deletions.
24 changes: 6 additions & 18 deletions src/libredirect.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ static void log_line(const char *fmt, ...)
}
#endif

static LONG load_lib(void)
static void load_lib(void)
{
#define LIBPCSC "libpcsclite_real.so.1"

Expand All @@ -140,15 +140,15 @@ static LONG load_lib(void)
if (NULL == Lib_handle)
{
log_line("loading \"%s\" failed: %s", lib, dlerror());
return SCARD_F_INTERNAL_ERROR;
return;
}

#define get_symbol(s) do { redirect.s = dlsym(Lib_handle, #s); if (NULL == redirect.s) { log_line("%s", dlerror()); return SCARD_F_INTERNAL_ERROR; } } while (0)
#define get_symbol(s) do { redirect.s = dlsym(Lib_handle, #s); if (NULL == redirect.s) { log_line("%s", dlerror()); return; } } while (0)

if (SCardEstablishContext == dlsym(Lib_handle, "SCardEstablishContext"))
{
log_line("Symbols dlsym error");
return SCARD_F_INTERNAL_ERROR;
return;
}

get_symbol(SCardEstablishContext);
Expand All @@ -169,29 +169,17 @@ static LONG load_lib(void)
get_symbol(SCardCancel);
get_symbol(SCardGetAttrib);
get_symbol(SCardSetAttrib);

return SCARD_S_SUCCESS;
}


/* exported functions */
PCSC_API LONG SCardEstablishContext(DWORD dwScope,
LPCVOID pvReserved1,
LPCVOID pvReserved2,
LPSCARDCONTEXT phContext)
{
LONG rv;
static int init = 0;
static pthread_once_t once_control = PTHREAD_ONCE_INIT;

if (!init)
{
init = 1;

/* load the real library */
rv = load_lib();
if (rv != SCARD_S_SUCCESS)
return rv;
}
pthread_once(&once_control, load_lib);

return redirect.SCardEstablishContext(dwScope, pvReserved1, pvReserved2,
phContext);
Expand Down

0 comments on commit f0f4fa1

Please sign in to comment.