Repository navigation
ctypes thread safety auditing (and fixing) #127945
Description
Feature or enhancement
This is a tracking issue for all thread safety problems related to ctypes. I'll be working on this, but others can feel free to give me some help.
First of all, we need to find where the thread safety problems are.
### Auditing
- [x] Audit `_ctypes.c`
- [ ] Audit `_ctypes_test.c` (and probably the generated file too)
- [ ] Audit `callbacks.c`
- [ ] Audit `callproc.c`
- [ ] Audit `cfield.c`
- [x] Audit `malloc_closure.c`
- [ ] Audit `stgdict.c`
I'll be tracking the issues that get found when auditing here. The plan is to just create a new issue and link to it for each new problem instead of flooding this issue with PRs.
Generally, the workflow for fixes should follow most of the rules from #116738, but I suspect we'll need recursive mutexes for quite a few things related to callbacks, because it's difficult to tell what might be re-entrant, and we can't use critical sections for arbitrary function pointers.
### Known Issues
- [ ] https://github.com/python/cpython/issues/127946
- [ ] https://github.com/python/cpython/issues/128182
- [ ] https://github.com/python/cpython/issues/128485
- [ ] https://github.com/python/cpython/issues/128567
- [ ] https://github.com/python/cpython/issues/128570
- [ ] https://github.com/python/cpython/issues/131974
cc @encukou, as the ctypes genius, and @colesbury as the free-threading mastermind.
Linked PRs
- gh-127945: add locking to malloc closure in free-threading #131662
- gh-127945: fix thread safety of ctypes state #131710
- gh-127945: fix thread safety of creating instances of ctypes structures #131716
- gh-127945: make initialization of error_object_name thread safe #131896
- gh-127945: acquire critical section around
PyCFuncPtr_call#131898 - gh-127945: mark TestLocalization as thread unsafe in ctypes #131899
- gh-127945: fix thread safety and add lock held assertions to paramfunc in ctypes #132473
- gh-127945: move initialization of field desc to module exec in ctypes #132552
- gh-127945: change _ctypes_test static globals to thread local #132575
- gh-127945: fix critical sections around ctypes array #132646
- gh-127945: skip more tests in ctypes when using parallel threads #132682
- gh-127945: add lock held assertions in ctypes arrays #132720
- gh-127945: add test_ctypes to free-threading TSAN CI #132727
- gh-127945: Update What's New in Python 3.14 for free-threaded ctypes #134332
- [3.14] gh-127945: Update What's New in Python 3.14 for free-threaded ctypes (GH-134332) #134364
Activity
encukou commentedon Jan 10, 2025
Thank you! I can review the ctypes parts :)
Heads-up: I'm currently working in
cfield.c/PyCField*; focus elsewhere to avoid conflicts.ZeroIntensity commentedon Jan 10, 2025
Got it, thanks! I'll probably just move to
callbacks.cnext.kumaraditya303 commentedon Mar 20, 2025
I discussed this with Peter and moving forward I'll be taking over the thread safety work and continue it.
kumaraditya303 commentedon Mar 24, 2025
I investigated the thread safety of ctypes and here's the (incomplete) list of issues:
dlmallocin_ctypes_alloc_callback. This is fixed by allocating a small memory block and freeing it in module initialization to force initialization of the allocator and is now thread safe with gh-128485: ensure that dlmalloc initializes itself at import time in ctypes #131633.malloc_closure.cis not thread safe in free-threading. This can be fixed by adding lock around the alloc and free functions in free-threading in gh-127945: add locking to malloc closure in free-threading #131662.PyCStructUnionType_update_stginfoneeds to be made thread safe as it modifies the type's data. This can be fixed by adding critical section around reading and writing to stginfo data in free-threading as using just mutex can lead to re-entrancy deadlocks.resizeare not thread safe and need to acquire critical section of the object being resized.colesbury commentedon Mar 24, 2025
I think there are also races on
StgInfo.flags, in particular with theDICTFLAG_FINALbit.cpython/Modules/_ctypes/_ctypes.c
Lines 718 to 719 in 4596666
kumaraditya303 commentedon Mar 24, 2025
Yes, I am covering that under "the initialization and concurrent modifications of stginfo is not thread safe".
colesbury commentedon Mar 24, 2025
This is different and more important than concurrent modification or initialization of stginfo, and I think it should be one of the early things we should focus on. Concurrent modifications of ctypes Structures is not an important use case.
However, creating separate instances of the same structure is an important use case:
This needs to be both efficient and thread-safe.
gh-127945: add locking to malloc closure in free-threading (#131662)
gh-127945: fix thread safety of ctypes state (#131710)
gh-127945: fix thread safety of creating instances of ctypes structur…
5 remaining items
gh-127945: fix thread safety and add lock held assertions to paramfun…
gh-127945: move initialization of field desc to module exec in ctypes (…
gh-127945: change `_ctypes_test.c` static globals to thread local (#1…
gh-127945: fix critical sections around ctypes array (#132646)
gh-127945: skip more tests in ctypes when using parallel threads (#13…
gh-127945: add lock held assertions in ctypes arrays (#132720)
gh-127945: add `test_ctypes` to free-threading TSAN CI (#132727)
sergey-miryanov commentedon May 15, 2025
Can this issue be closed now as all linked PRs have been merged? Is there anything else that needs to be done?
gh-127945: Update What's New in Python 3.14 for free-threaded ctypes (#…
pythongh-127945: Update What's New in Python 3.14 for free-threaded c…
[3.14] gh-127945: Update What's New in Python 3.14 for free-threaded …
pythongh-127945: Update What's New in Python 3.14 for free-threaded c…
pythongh-127945: Update What's New in Python 3.14 for free-threaded c…
pythongh-127945: Update What's New in Python 3.14 for free-threaded c…