I am not sure that this is even the best end state to reach in a GIL-free world. It may be that it is better to have some APIs that are not thread-safe and are simply documented as such, especially if normal usage of the library is thread-safe anyway.
I have looked at downstream usage of python-flint and it would be thread-safe because it either does not use the potentially unsafe features or only uses them in way that would be thread-safe (e.g. only mutating an object at construction before it can be shared).
For now I will document how to use the library in a thread-safe way. It is not clear to me yet whether documenting this and then guaranteeing “thread-safe when used as documented” is a better end state than guaranteeing no “seg-faults ever regardless of invalid usage”. Of course it would be nice to prevent the segfaults but we don’t yet know what the cost of that would be e.g. the performance impact it would have for people who are already using it in a thread-safe way.
I have confirmed now that I can crash the free-threaded interpreter with python-flint but only by doing things that would not be thread-safe anyway. The difference is just that you’re getting crashes inside malloc whereas if we put locks everywhere then you would get random data corruption or non-deterministic output instead. Personally I prefer segfaults over non-deterministic output. If the user really wants to get something sensible here then they are going to need to use their own locks anyway.
What this means is that it is not clear to me what the criteria are supposed to be for using Py_MOD_GIL_NOT_USED
. So far the only example I know of for wheels on PyPI is NumPy which has already uploaded cp313t wheels and has set the flag so you can use it without the GIL by default. It is still possible to resize an array:
>>> a = np.array([1, 2])
>>> a.resize((10,))
>>> a
array([1, 2, 0, 0, 0, 0, 0, 0, 0, 0])
I assume that there are no locks to prevent other threads from accessing the data during a resize.
The only other example I know of is Cython which has not published wheels yet but if you install the master branch under cp313t and then use it to build python-flint it prints out 50 annoying warnings about enabling the GIL. This is because of Cython’s own extension modules even though it is not being used in any multithreaded way. We use meson for multiprocess parallelisation which is cleaner in a build tool but it runs the cython
CLI 50 times, hence 50 warnings. I don’t know if that is something that will be changed by the time Cython puts out an actual 3.1 release.
Is there any way for Cython itself to disable the warning besides setting Py_MOD_GIL_NOT_USED
? Note that the cython
CLI can guarantee that multiple threads will never be used so that the warning is pointless either way.