GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Data race between `deque.index` and `deque` mutators on `Py_SIZE` with free-threading · Issue #150750 · python/cpython

Data race between deque.index and deque mutators on Py_SIZE with free-threading #150750

New issue
Copy link
New issue
Copy link
Closed
Closed
Data race between deque.index and deque mutators on Py_SIZE with free-threading#150750
Copy link
Assignees
sobolevn
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-argument-clinictopic-free-threadingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@Naserume
Naserume
opened on Jun 2, 2026
Issue body actions

Bug report

Bug description:

deque_index's clinic input declares stop's default as Py_SIZE(deque),

cpython/Modules/_collectionsmodule.c

Lines 1247 to 1255 in 160dc74

@text_signature "($self, value, [start, [stop]])"
_collections.deque.index as deque_index
deque: dequeobject
value as v: object
start: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='0') = NULL
stop: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='Py_SIZE(deque)') = NULL
/

and the generated wrapper reads Py_SIZE(deque) non-atomically before entering the critical_section.

cpython/Modules/clinic/_collectionsmodule.c.h

Lines 337 to 343 in 160dc74

static PyObject *
deque_index(PyObject *deque, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *v;
Py_ssize_t start = 0;
Py_ssize_t stop = Py_SIZE(deque);

Meanwhile mutators (deque_clear, deque_append_lock_held, deque_appendleft_lock_held) update the same field via Py_SET_SIZE.

cpython/Modules/_collectionsmodule.c

Line 356 in 160dc74

Py_SET_SIZE(deque, Py_SIZE(deque) + 1);

cpython/Modules/_collectionsmodule.c

Line 405 in 160dc74

Py_SET_SIZE(deque, Py_SIZE(deque) + 1);

cpython/Modules/_collectionsmodule.c

Line 763 in 160dc74

Py_SET_SIZE(deque, 0);

Reproducer:

import collections
from threading import Thread, Barrier

d = collections.deque(range(100))

N_MUT = 3
ITERS = 10000
barrier = Barrier(1 + N_MUT)

def index_thread():
    barrier.wait()
    for _ in range(ITERS):
        try:
            d.index(50)
        except ValueError:
            pass

def mut_thread():
    barrier.wait()
    for _ in range(ITERS):
        d.append(0)
        d.clear()
        d.extend(range(100))
        d.appendleft(-1)

if __name__ == "__main__":
    threads = [Thread(target=index_thread)]
    threads += [Thread(target=mut_thread) for _ in range(N_MUT)]
    for t in threads: t.start()
    for t in threads: t.join()

TSAN Report:

WARNING: ThreadSanitizer: data race (pid=745816)
  Read of size 8 at 0x7fffb63e9f20 by thread T1:
    #0 deque_index /cpython/./Modules/clinic/_collectionsmodule.c.h:343:23 (python3.16t+0x5bd290) 
    #1 method_vectorcall_FASTCALL /cpython/Objects/descrobject.c:402:24 (python3.16t+0x22e771) 
    #2 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.16t+0x2149a8) 
    #3 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.16t+0x2149a8)
    #4 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:766:11 (python3.16t+0x4370c8) 
    #5 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1846:35 (python3.16t+0x43d022) 
    #6 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:122:16 (python3.16t+0x436463) 
    #7 _PyEval_Vector /cpython/Python/ceval.c:2134:12 (python3.16t+0x436463)
    #8 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.16t+0x215013) 
    #9 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.16t+0x216b11) 
    #10 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.16t+0x216b11)
    #11 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.16t+0x21a132) 
    #12 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.16t+0x48ec15) 
    #13 context_run /cpython/Python/context.c:728:29 (python3.16t+0x48ec15)
    #14 method_vectorcall_FASTCALL_KEYWORDS /cpython/Objects/descrobject.c:421:24 (python3.16t+0x22e84c) 
    #15 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.16t+0x2149a8) 
    #16 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.16t+0x2149a8)
    #17 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:766:11 (python3.16t+0x4370c8) 
    #18 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1846:35 (python3.16t+0x43d022) 
    #19 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:122:16 (python3.16t+0x436463) 
    #20 _PyEval_Vector /cpython/Python/ceval.c:2134:12 (python3.16t+0x436463)
    #21 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.16t+0x215013) 
    #22 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.16t+0x216b11) 
    #23 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.16t+0x216b11)
    #24 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.16t+0x21a132) 
    #25 _PyVectorcall_Call /cpython/Objects/call.c:273:16 (python3.16t+0x214ca2) 
    #26 _PyObject_Call /cpython/Objects/call.c:348:16 (python3.16t+0x214ca2)
    #27 PyObject_Call /cpython/Objects/call.c:373:12 (python3.16t+0x214d07) 
    #28 thread_run /cpython/./Modules/_threadmodule.c:388:21 (python3.16t+0x61a708) 
    #29 pythread_wrapper /cpython/Python/thread_pthread.h:234:5 (python3.16t+0x5473bb) 

  Previous atomic write of size 8 at 0x7fffb63e9f20 by thread T2:
    #0 _Py_atomic_store_ssize_relaxed /cpython/./Include/cpython/pyatomic_gcc.h:513:3 (python3.16t+0x5bc41e) 
    #1 _Py_SET_SIZE_impl /cpython/./Include/object.h:258:5 (python3.16t+0x5bc41e)
    #2 deque_append_lock_held /cpython/./Modules/_collectionsmodule.c:356:5 (python3.16t+0x5bc41e)
    #3 deque_extend_impl /cpython/./Modules/_collectionsmodule.c:514:13 (python3.16t+0x5bbeaf) 
    #4 deque_extend /cpython/./Modules/clinic/_collectionsmodule.c.h:127:20 (python3.16t+0x5bc29b) 
    #5 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:4261:35 (python3.16t+0x443538) 
    #6 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:122:16 (python3.16t+0x436463) 
    #7 _PyEval_Vector /cpython/Python/ceval.c:2134:12 (python3.16t+0x436463)
    #8 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.16t+0x215013) 
    #9 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.16t+0x216b11) 
    #10 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.16t+0x216b11)
    #11 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.16t+0x21a132) 
    #12 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.16t+0x48ec15) 
    #13 context_run /cpython/Python/context.c:728:29 (python3.16t+0x48ec15)
    #14 method_vectorcall_FASTCALL_KEYWORDS /cpython/Objects/descrobject.c:421:24 (python3.16t+0x22e84c) 
    #15 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.16t+0x2149a8) 
    #16 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.16t+0x2149a8)
    #17 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:766:11 (python3.16t+0x4370c8) 
    #18 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1846:35 (python3.16t+0x43d022) 
    #19 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:122:16 (python3.16t+0x436463) 
    #20 _PyEval_Vector /cpython/Python/ceval.c:2134:12 (python3.16t+0x436463)
    #21 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.16t+0x215013) 
    #22 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.16t+0x216b11) 
    #23 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.16t+0x216b11)
    #24 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.16t+0x21a132) 
    #25 _PyVectorcall_Call /cpython/Objects/call.c:273:16 (python3.16t+0x214ca2) 
    #26 _PyObject_Call /cpython/Objects/call.c:348:16 (python3.16t+0x214ca2)
    #27 PyObject_Call /cpython/Objects/call.c:373:12 (python3.16t+0x214d07) 
    #28 thread_run /cpython/./Modules/_threadmodule.c:388:21 (python3.16t+0x61a708) 
    #29 pythread_wrapper /cpython/Python/thread_pthread.h:234:5 (python3.16t+0x5473bb) 

...

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

  • gh-150750: Fix a race condition in deque.index with free-threading #150779
  • [3.15] gh-150750: Fix a race condition in deque.index with free-threading (GH-150779) #150920
  • [3.14] gh-150750: Fix a race condition in deque.index with free-threading (GH-150779) #150921

Activity

  1. Naserume
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Jun 2, 2026
  2. StanFromIreland
    added
    extension-modulesC modules in the Modules dirC modules in the Modules dir
    topic-free-threading
    on Jun 2, 2026
  3. sobolevn
    added
    topic-argument-clinic
    on Jun 2, 2026
  4. sobolevn
    self-assigned this
    on Jun 2, 2026
  5. sobolevn
    added 4 commits that reference this issue on Jun 2, 2026

    pythongh-150750: Fix a race condition in `deque.index` with free-thre…

    c715214

    gh-150750: Fix a race condition in `deque.index` with free-threading (#…

    d83d50b

    [3.14] gh-150750: Fix a race condition in `deque.index` with free-thr…

    2d3d11c

    [3.15] gh-150750: Fix a race condition in `deque.index` with free-thr…

    42a41cc
  6. sobolevn
    closed this as completedon Jun 4, 2026
  7. philthompson10
    added a commit that references this issue on Jun 17, 2026

    pythongh-150750: Fix a race condition in `deque.index` with free-thre…

    70fd181
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @sobolevn
    sobolevn

Labels

extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-argument-clinictopic-free-threadingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.