python / python/cpython

Data race in list.sort() on no-gil build

Aperta
#154,756 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

interpreter-core topic-free-threading type-bug
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Bug report

Bug description:
Summary

As reported in #153852 (TSAN0014), list.sort() writes each slot of the array with a plain, non-atomic store. When another thread concurrently accesses the same list, there is a data race between the in-place sort and the reader, which will be reported by TSAN.

How to reproduce

First we need to enable thread-sanitizer

  • ./configure --disable-gil --with-thread-sanitizer
  • TSAN_OPTIONS="halt_on_error=1 symbolize=1 history_size=4" ./python repro.py

Then run the following repro.py

import sys, threading

size, rounds, num_threads = 2000, 1500, 32
SCRAMBLED = sorted(range(size), key=lambda x: (x * 2654435761) & 0xFFFFFFFF)
global_list = list(SCRAMBLED)
enter, leave = threading.Barrier(num_threads + 1), threading.Barrier(num_threads + 1)

def reader():
    for _ in range(rounds):
        enter.wait()
        for _x in global_list:
            pass
        leave.wait()

def main_sorter():
    for _ in range(rounds):
        global_list[:] = SCRAMBLED
        enter.wait()
        global_list.sort()
        leave.wait()

ts = [threading.Thread(target=reader) for _ in range(num_threads)]
for t in ts: 
    t.start()
main_sorter()
for t in ts: 
    t.join()

Finally we could see the log from TSan

WARNING: ThreadSanitizer: data race (pid=3143552)
  Write of size 8 at 0xffffb6b3c018 by main thread:
    #0 binarysort Objects/listobject.c:1918 (python+0x1c64bc)
CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs
  • gh-154572

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia eseguendo repro.py con la configurazione no-GIL e ThreadSanitizer indicata, quindi esamina Objects/listobject.c intorno a binarysort alla riga 1918. Confronta il report della race con il lavoro collegato gh-154572. Il lavoro è completato quando la riproduzione non produce più un report di data race di ThreadSanitizer.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
c, python
Ambito
operating-systems, testing-qa
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
30/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.