Skip to content

Possible data race in dictiter_iternext with with free-threading build #148873

@Naserume

Description

@Naserume

Bug description:

With free-threading, it is possible to read di->di_dict, while it is being written.

cpython/Objects/dictobject.c

Lines 5611 to 5615 in f93834f

static PyObject*
dictiter_iternextkey(PyObject *self)
{
dictiterobject *di = (dictiterobject *)self;
PyDictObject *d = di->di_dict;

cpython/Objects/dictobject.c

Lines 5848 to 5862 in f93834f

di->di_pos = i+1;
di->len--;
if (out_key != NULL) {
*out_key = Py_NewRef(key);
}
if (out_value != NULL) {
*out_value = Py_NewRef(value);
}
return 0;
fail:
di->di_dict = NULL;
Py_DECREF(d);
return -1;
}

Reproducer:

import threading

d = {str(i): i for i in range(1000)}
it = iter(d)

barrier = threading.Barrier(2)


def run():
    barrier.wait()
    for _ in range(10000):
        try:
            next(it)
        except StopIteration:
            pass


t1 = threading.Thread(target=run)
t2 = threading.Thread(target=run)
t1.start()
t2.start()
t1.join()
t2.join()

TSAN report:

WARNING: ThreadSanitizer: data race (pid=2919507)
  Write of size 8 at 0x7fffb66d6bf0 by thread T2:
    #0 dictiter_iternextitem_lock_held /cpython/Objects/dictobject.c:5859:17 (python3.15t+0x2ada61) 
    #1 dictiter_iternext_threadsafe /cpython/Objects/dictobject.c:5995:11 (python3.15t+0x2ada61)
    #2 dictiter_iternextkey /cpython/Objects/dictobject.c:5622:9 (python3.15t+0x2a2211) 
    #3 builtin_next /cpython/Python/bltinmodule.c:1764:11 (python3.15t+0x423b62) 
    #4 _Py_BuiltinCallFast_StackRef /cpython/Python/ceval.c:824:11 (python3.15t+0x43223d) 
    #5 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:2409:35 (python3.15t+0x43223d)
    #6 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x429900) 
    #7 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x429900)
    #8 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x21131f) 
    #9 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x212e59) 
    #10 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x212e59)
    #11 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21638f) 
    #12 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x481401) 
    #13 context_run /cpython/Python/context.c:727:29 (python3.15t+0x481401)
    #14 method_vectorcall_FASTCALL_KEYWORDS /cpython/Objects/descrobject.c:421:24 (python3.15t+0x22b067) 
    #15 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x210ca3) 
    #16 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x210ca3)
    #17 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:775:11 (python3.15t+0x42a52c) 
    #18 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1846:35 (python3.15t+0x43031e) 
    #19 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x429900) 
    #20 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x429900)
    #21 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x21131f) 
    #22 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x212e59) 
    #23 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x212e59)
    #24 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21638f) 
    #25 _PyVectorcall_Call /cpython/Objects/call.c:273:16 (python3.15t+0x210fab) 
    #26 _PyObject_Call /cpython/Objects/call.c:348:16 (python3.15t+0x210fab)
    #27 PyObject_Call /cpython/Objects/call.c:373:12 (python3.15t+0x211015) 
    #28 thread_run /cpython/./Modules/_threadmodule.c:388:21 (python3.15t+0x606be2) 
    #29 pythread_wrapper /cpython/Python/thread_pthread.h:234:5 (python3.15t+0x536447) 

  Previous read of size 8 at 0x7fffb66d6bf0 by thread T1:
    #0 dictiter_iternextkey /cpython/Objects/dictobject.c:5615:27 (python3.15t+0x2a21f9) 
    #1 builtin_next /cpython/Python/bltinmodule.c:1764:11 (python3.15t+0x423b62) 
    #2 _Py_BuiltinCallFast_StackRef /cpython/Python/ceval.c:824:11 (python3.15t+0x43223d) 
    #3 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:2409:35 (python3.15t+0x43223d)
    #4 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x429900) 
    #5 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x429900)
    #6 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x21131f) 
    #7 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x212e59) 
    #8 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x212e59)
    #9 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21638f) 
    #10 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x481401) 
    #11 context_run /cpython/Python/context.c:727:29 (python3.15t+0x481401)
    #12 method_vectorcall_FASTCALL_KEYWORDS /cpython/Objects/descrobject.c:421:24 (python3.15t+0x22b067) 
    #13 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x210ca3) 
    #14 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x210ca3)
    #15 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:775:11 (python3.15t+0x42a52c) 
    #16 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1846:35 (python3.15t+0x43031e) 
    #17 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x429900) 
    #18 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x429900)
    #19 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x21131f) 
    #20 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x212e59) 
    #21 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x212e59)
    #22 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21638f) 
    #23 _PyVectorcall_Call /cpython/Objects/call.c:273:16 (python3.15t+0x210fab) 
    #24 _PyObject_Call /cpython/Objects/call.c:348:16 (python3.15t+0x210fab)
    #25 PyObject_Call /cpython/Objects/call.c:373:12 (python3.15t+0x211015) 
    #26 thread_run /cpython/./Modules/_threadmodule.c:388:21 (python3.15t+0x606be2) 
    #27 pythread_wrapper /cpython/Python/thread_pthread.h:234:5 (python3.15t+0x536447) 

CPython versions tested on:

Python 3.15.0a8+ free-threading build (heads/main:f93834ff011, Apr 22 2026, 11:41:06)

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions