Skip to content

nogil list reverse breaks atomicity #129619

@luisggpina

Description

@luisggpina

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

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions