7 ms·
C code needs to be updated to be safe in a GIL free execution environment. It is a lot of work! The pervasive problem is that mutable data structures (lists,
by rogerbinns 11mo ago
C code needs to be updated to be safe in a GIL free execution environment. It is a lot of work! The pervasive problem is that mutable data structures (lists, dict etc) could change at any arbitrary point while the C code is working with them, and the reference count for others could drop to zero if *anyone* is using a borrowed reference (common for performance in CPython APIs). Previously the GIL protected where those changes could happen. In simple cases it is adding a critical section, but often there multiple data structures in play. As an example these are the changes that had to be done to the standard library json module:
https://github.com/python/cpython/pull/119438/files#diff-efe183ae0b85e5b8d9bbbc588452dd4de80b39fd5c5174ee499ba554217a39ed https://github.com/python/cpython/pull/119438/files#diff-efe...
This is how much of the standard library has been audited:
https://github.com/python/cpython/issues/116738 https://github.com/python/cpython/issues/116738
The json changes above are in Python 3.15, not the just released 3.14.
The consequences of the C changes not being made are crashes and corruption if unexpected mutation or object freeing happens. Web services are exposed to adversity so be *very* careful.
It would be a big help if CPython released a tool that could at least scan a C code base to detect free threaded issues, and ideally verify it is correct.
- westurner 11mo ago> It would be a big help if CPython released a tool that could at least scan a C code base to detect free threaded issues, and ideally verify it is correct. Create or extend a list of answers to: What heuristics predict that code will fail in CPython's nogil "free threaded" mode?
- rogerbinns 11mo agoSome of that is already around, but scattered across multiple locations. For example there is a list in the Python doc: https://docs.python.org/3/howto/free-threading-extensions.html#borrowed-references https://docs.python.org/3/howto/free-threading-extensions.ht... And a dedicated web site: https://py-free-threading.github.io/ https://py-free-threading.github.io/ But as an example neither include PySequence_Fast which is in the json.c changes I pointed to. The folks doing the auditing of stdlib do have an idea of what they are looking for, and so would be best suited to keep a list (and tool) up to date with what is needed.
- westurner 11mo agoA list of Issue and PR URLs that identify and fix free threading issues would likely also be of use for building a 2to3-like tool to lint and fix C extensions to work with CPython free threading nogil mode
- dehrmann 11mo agoI think Java got this mostly right. On the threading front, very little is thread-safe or atomic (x += 1 is not thread-safe), so as soon as you expose something to threads, you have to think about safe access. For interacting with C code, your choices are either shared buffers or copying data between C and Java. It's painful, but it's needed for memory safety.
- colonCapitalDee 11mo agoIs compound assignment atomic in any major language?
- arccy 11mo agono... but some languages may disallow simultaneously holding a reference in different execution threads
- Groxx 11mo agoit has been in Python due to the GIL.
- i80and 11mo agoIt's not atomic even with the GIL, though: another thread can run in between the bytecode's load and increment, right? The GIL's guarantees didn't extend to this.
- deleted 11mo ago[deleted]
- Groxx 11mo agoThere is NB_INPLACE_ADD... but I'm struggling to find enough details to be truly confident :\ possibly its existence is misleading other people (thus me) to think += is a single operation in bytecode. Or, on further reading, maybe it applies to anything that implements `_iadd_` in C. Which does not appear to include native longs: https://github.com/python/cpython/blob/main/Objects/longobject.c#L6621 https://github.com/python/cpython/blob/main/Objects/longobje...
- radarsat1 11mo agoI agree and honestly it may as well be considered a form of ABI incompatibility. They should make this explicit such that existing C extensions need to be updated to use some new API call for initialization to flag that they are GILless-ready, so that older extensions cannot even successfully be loaded when GIL is disabled.
- electroglyph 11mo agothe problem with that is it effects the entire application and makes the whole thing free-threading incompatible. it's quite possible to make a python app that requires libraries A and B to be able to be loaded into a free-threaded application, but which doesn't actually do any unsafe operations with them. we need to be able to let people load these libraries, but say: this thing may not be safe, add your own mutexes or whatever
- rogerbinns 11mo agoThis has already been done. There is a 't' suffix in the ABI tag. You have to explicitly compile the extension against a free threaded interpreter in order to get that ABI tag in your extension and even be able to load the extension. The extension then has to opt-in to free threading in its initialization. If it does not opt-in then a message appears saying the GIL has been enabled, and the interpreter continues to run with the GIL. This may seem a little strange but is helpful. It means the person running Python doesn't have to keep regular and free threaded Python around, and duplicate sets of extensions etc. They can just have the free threaded one, anything loaded that requires the GIL gives you the normal Python behaviour. What is a little more problematic is that some of the standard library is marked as supporting free threading, even though they still have the audit and update work outstanding. Also the last time I checked, the compiler thread sanitizers can't work with free threaded Python.
- sgammon 11mo ago> “at least scan a C code base to detect free threaded issues” if such a thing were possible, thread coordination would not have those issues in the first place
- rogerbinns 11mo agoSome examples of what it could do when using the C Python APIs: * Point out using APIs that return borrowed references * Suggest assertions that critical sections are held when operating on objects * Suggest alternate APIs * Recognise code patterns that are similar to those done during the stdlib auditing work The compiler thread sanitizers didn't work the last time I checked - so get them working. Edit: A good example of what can be done is Coccinelle used in the Linux kernel which can detect problematic code (locking is way more complex!) as well as apply source transformations. https://www.kernel.org/doc/html/v6.17/dev-tools/coccinelle.html https://www.kernel.org/doc/html/v6.17/dev-tools/coccinelle.h...