-
-
Notifications
You must be signed in to change notification settings - Fork 34.3k
Description
Crash report
What happened?
The array module sets {Py_mod_gil, Py_MOD_GIL_NOT_USED} in its module
slots, claiming free-threading support. None of its methods hold any
lock when accessing the internal buffer pointer ob_item. Concurrent
arr.clear() + arr[i] reliably produces a seg fault.
Build the latest cpython with --disable-gil.
Reproducer Code
import array
import sys
import threading
if sys._is_gil_enabled():
sys.exit("EXIT: requires --disable-gil build")
NUM_THREADS = 4
ITERS = 5_000_000
arr = array.array('i', list(range(10)))
def reader():
for _ in range(ITERS):
try:
_ = arr[0]
except IndexError:
pass
def writer():
for _ in range(ITERS):
arr.clear()
arr.extend(range(10))
readers = [threading.Thread(target=reader) for _ in range(NUM_THREADS)]
writers = [threading.Thread(target=writer) for _ in range(NUM_THREADS)]
for t in writers + readers:
t.start()
for t in writers + readers:
t.join()
print("COMPLETE: without crash — race may not have triggered this run.")
print("Re-run on a multi-core machine, or increase NUM_THREADS / ITERS")When running it, I observed:
Exception in thread Thread-5 (writer):
Exception in thread Thread-7 (writer):
Exception in thread Thread-6 (writer):
Traceback (most recent call last):
File "/Users/chs/builds/bin/lib/python3.15t/threading.py", line 1075, in _bootstrap_inner
self._context.run(self.run)
File "/Users/chs/builds/bin/lib/python3.15t/threading.py", line 1017, in run
self._target(*self._args, **self._kwargs)
File "/Users/chs/PycharmProjects/Scratch/toctou1.py", line 22, in writer
arr.extend(range(10))
IndexError: array assignment index out of range
Traceback (most recent call last):
Traceback (most recent call last):
[1] 51460 segmentation fault ./python3 /Users/chs/PycharmProjects/Scratch/toctou1.py
Root Cause:
Modules/arraymodule.c has no @critical_section annotations and no atomic operations on ob_item. array_resize(0) frees and nulls ob_item without any lock, while array_item reads ob_size and then dereferences ob_item without any lock. The same problem likely affects other methods.
CPython versions tested on:
3.15
Operating systems tested on:
macOS
Output from running 'python -VV' on the command line:
Python 3.15.0a7+ free-threading build (heads/main:e167e06f8c6, Mar 15 2026, 09:14:39) [Clang 17.0.0 (clang-1700.6.4.2)]