nogil list `reverse` breaks atomicity
@sobolevn y travaille déjà.
Depuis le 4/2/2025.
- Langage dominant
- Python
- Étoiles
- 77.2k
- Forks
- 35.9k
- Métriques de merge des PR
- Métriques de PR en attente
Description
Bug report
Bug description:
Hi,
We're a research group focused on testing concurrent runtimes. Our work-in-progress prototype found a violation of atomicity on the current nogil build when using list reverse with other concurrent operations on the same list. The program below shows the wrong behavior for reverse and __contains__:
import threading
import sys
def t0(b1,s,res):
b1.wait()
s.reverse()
def t1(b1,s,res):
b1.wait()
res.append(s.__contains__(3))
def Test():
l = [1, 2, 3]
threads=[]
barrier = threading.Barrier(2)
res = []
threads.append(threading.Thread(target= t0, args=(barrier, l,res)))
threads.append(threading.Thread(target= t1, args=(barrier, l,res)))
for i in range(0, len(threads)):
threads[i].start()
for i in range(0, len(threads)):
threads[i].join()
if res[0] != True:
print("found bug: " + str(res))
print("test begin...")
for i in range(0,50000):
threads = []
if i % 1000 == 0:
print(i)
for i in range(0,100):
threads.append(threading.Thread(target= Test))
for t in threads:
t.start()
for t in threads:
t.join()
print("test Done")
Operation __contains__ should always see element 3 in the list, either the original or reversed. However, it can see a list without element 3 and return False, as shown in the sample output:
test begin...
0
found bug: [False]
found bug: [False]
1000
We observed the same behavior with operations count and index executing concurrently with reverse on the same list, I'll add a comment with those tests and sample outputs.
@flypoodles and @overlorde are part of the team, adding them so they get notified about further discussion.
We note that we observed these outputs in several x86_64 machines and one ARM machine.
CPython versions tested on:
3.14, CPython main branch
Operating systems tested on:
Linux
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Évaluation
Cette issue n'a pas encore été évaluée.