You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sf_error(NULL) race condition: LibsndfileError.code=0 under concurrent sf_open_virtual calls #479
When multiple threads concurrently call sf_open_virtual() on unsupported formats (e.g. MP4 bytes), the resulting LibsndfileError sometimes has code=0 instead of the correct error code (e.g. 1 for "Format not recognised"). This is because _open() at soundfile.py:L1264 calls sf_error(NULL) to retrieve the error code after a failed open, and sf_error(NULL) reads a global (non-thread-safe) error variable in libsndfile.
When thread A fails sf_open_virtual and thread B also fails concurrently, thread B's call to sf_error(NULL) may return 0 because thread A's subsequent operations (or libsndfile's internal cleanup) have already cleared the global error state.
This results in LibsndfileError with:
code = 0
error_string = "(Garbled error message from libsndfile)"
Running this repeatedly will produce code=0 on some threads.
Impact
Callers that branch on LibsndfileError.code to distinguish error types (e.g. "unrecognised format" vs "corrupt file") get incorrect codes under concurrency, leading to wrong error-handling paths.
Environment
soundfile==0.13.1
libsndfile 1.2.2
Python 3.12, Linux x86_64
Possible fix
soundfile.py:_open() could use sf_error() on the (failed) file handle instead of sf_error(NULL), but since the handle is NULL on open failure, libsndfile doesn't support that. An alternative is to add a module-level lock around the sf_open_virtual + sf_error(NULL) sequence so the global error state can't be clobbered between the two calls.
Activity