python / python/cpython

Data race on `kqueue.kqfd` between `close()` and the `closed` getter with free-threading build

Offen
#151,364 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

topic-free-threading type-bug
Vorherrschende Sprache
Python
Sterne
77.2k
Forks
35.9k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Bug report

Bug description:

select.kqueue accesses its internal kqfd file-descriptor field with no synchronization. So kqueue.close() can write the kqfd,

https://github.com/python/cpython/blob/b18168cb32d545ed976b760983478cbd5dde5bdf/Modules/selectmodule.c#L2160-L2165

while the closed getter reads it.

https://github.com/python/cpython/blob/b18168cb32d545ed976b760983478cbd5dde5bdf/Modules/selectmodule.c#L2276-L2279

Reproducer:

import select
from threading import Thread

slot = [select.kqueue()]

def reader():
    for _ in range(200000):
        try:
            _ = slot[0].closed
        except Exception:
            pass

def churner():
    for _ in range(200000):
        kq = select.kqueue()
        slot[0] = kq
        kq.close()

threads  = [Thread(target=reader)  for _ in range(4)]
threads += [Thread(target=churner) for _ in range(4)]
for t in threads: t.start()
for t in threads: t.join()

TSAN Report:

==================
WARNING: ThreadSanitizer: data race (pid=28784)
  Write of size 4 at 0x00011c040140 by thread T5:
    #0 kqueue_queue_internal_close selectmodule.c:2165
    #1 select_kqueue_close selectmodule.c.h:1189
    #2 method_vectorcall_NOARGS descrobject.c:448
    #3 PyObject_Vectorcall call.c:327
    #4 _Py_VectorCallInstrumentation_StackRefSteal ceval.c:766
    #5 _PyEval_EvalFrameDefault generated_cases.c.h:1846
...

  Previous read of size 4 at 0x00011c040140 by thread T4:
    #0 kqueue_queue_get_closed selectmodule.c:2279
    #1 getset_get descrobject.c:194
    #2 _PyObject_GenericGetAttrWithDict object.c
    #3 PyObject_GenericGetAttr object.c:2012
    #4 _PyObject_GetAttrStackRef object.c
    #5 _PyEval_EvalFrameDefault generated_cases.c.h:8312

SUMMARY: ThreadSanitizer: data race selectmodule.c:2165 in kqueue_queue_internal_close
==================
CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs
  • gh-151376

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne in Modules/selectmodule.c bei kqueue_queue_internal_close ungefähr in Zeile 2165 und bei kqueue_queue_get_closed ungefähr in Zeile 2279 und prüfe anschließend den Reproducer und den TSAN-Bericht. Sieh dir den verknüpften PR gh-151376 auf bereits laufende Arbeiten an; abgeschlossen ist die Aufgabe, wenn das nebenläufige close() und der Zugriff auf closed nicht mehr den gemeldeten Race-Zustand oder die Descriptor-Gefahr verursachen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
c, python
Bereich
operating-systems
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
20/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.