question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Possible race-condition while writing bytecode when rewriting assertions

See original GitHub issue

Since we started porting to Python 3, our builds on Windows fail sometimes, say 5-10% of the runs, in a bizarre and random manner:

___________ ERROR at setup of testMeshAssemblyPlaneControllerNoBBox ___________
[gw3] win32 -- Python 3.5.3 W:\Miniconda\envs\_sci20-win64g-py35\python.exe
file K:\etk\sci20\source\python\sci20\app\mesh_assembly\plane\_tests\test_mesh_assembly_plane_controller.py, line 83
  def testMeshAssemblyPlaneControllerNoBBox(almost_equal):
E       fixture 'py5' not found

Strangely the “name” being reported is always py and some digits, like py2, py7 or py44.

This always happens when running with xdist and in a random test or contest file, which suggest that the assertion rewriting code might some bug in its locking code when writing the rewritten bytecode to the disk, corrupting it.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
nicoddemuscommented, Apr 11, 2018

The code responsible for writing the pyc files is this:

https://github.com/pytest-dev/pytest/blob/e012dbe346d724d91993068c6f5cb15423bb167e/_pytest/assertion/rewrite.py#L341-L352

Unfortunately the comment about Windows is not correct, there’s no exclusive access guarantee and it is possible for concurrent processes/threads to write to a file at the same time and possibly corrupt it.

This short script demonstrates this:

import os
import tempfile
import threading

with tempfile.TemporaryDirectory() as tmpdir:
    filename = os.path.join(tmpdir, 'somefile.txt')
    print(f'FILE: {filename}')

    COUNT = 10

    data = [1025 * 1024 * str(i) for i in range(COUNT)]


    def write(i):
        with open(filename, 'w') as f:
            f.write(data[i])

    threads = [threading.Thread(target=write, args=(i,)) for i in range(COUNT)]
    for t in threads:
        t.start()

    for t in threads:
        t.join()

    print('DONE')
    
    with open(filename) as f:
        read_data = set(f.read())

    print(f'READ: {read_data}')

It spawns a number of threads, all of them writing different data to the same file. At the end, it counts how many different characters were written to the file.

Most of the time the output is this:

FILE: C:\Users\Bruno\AppData\Local\Temp\tmpzzgwfa99\somefile.txt
DONE
READ: {'2'}

But sometimes (2/9 on my machine) the file ends up corrupted:

FILE: C:\Users\Bruno\AppData\Local\Temp\tmpm0o7bpuq\somefile.txt
DONE
READ: {'8', '9'}

This behavior is consistent with the CI failures we have seen: corrupted .pyc files around 2-3% of the time.

I searched for some solutions about the problem of atomically renaming a file on multiple platforms and the best library I found was python-atomicwrites, which is small and does just this job.

0reactions
nicoddemuscommented, Apr 12, 2018

@maiksensi were you experiencing this as well?

Read more comments on GitHub >

github_iconTop Results From Across the Web

What is a race condition? - Stack Overflow
A race condition occurs when two or more threads can access shared data and they try to change it at the same time....
Read more >
Data races in Python, despite the Global Interpreter Lock
The article mixes up data races and race conditions, which is understandable since it's a common mistake. Race conditions are a fairly general...
Read more >
How to avoid race around in concurrent assertion
I am observing a race around where src_data may have #0 glitch and assertion is false firing. How do I rewrite this?
Read more >
VICTORIA UNIVERSITY OF WELLINGTON Te Whare Wananga o te ...
Compile-time rewriting of the bytecode, to add the ability for a thread to ... Whiley is embodied in actors, it's not possible for...
Read more >
JUnit 5 User Guide
To find out what features are available in JUnit 5 and how to use them, ... race condition of writing and then reading...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found