Skip to content

Free-threaded CI: test_chunks_is_lazy counter race miscounts decodes (15 != 16) #3363

Description

@brendancol

Describe the bug

The free-threaded (3.14t) full-suite CI job on main fails on one test:

FAILED xrspatial/geotiff/tests/vrt/test_window.py::test_chunks_is_lazy_does_not_call_internal_reader
  AssertionError: expected 16 per-chunk decodes after compute, got 15

(run 27626148337, job 81688172532). Every other test passes (9696 passed).

Root cause

The test instruments the internal VRT reader with a counting wrapper:

counter = {'calls': 0}
def counting_read(*args, **kwargs):
    counter['calls'] += 1
    return real_read(*args, **kwargs)

result.compute() on a 4x4 = 16-chunk dask array runs the 16 decode tasks through dask's threaded scheduler. Under PYTHON_GIL=0 (set on the 3.14t pytest step) those tasks run truly in parallel, and counter['calls'] += 1 is a non-atomic read-modify-write: two threads read the same value and write back the same increment, losing one. So 16 real decodes are counted as 15.

This is a test-instrumentation thread-safety bug, not a product bug. The chunked decode correctly runs 16 times; only the counter miscounts. The test runs in both the fast and full lanes (it is not slow-marked); the race is probabilistic, so it slipped through #3360's 3.14t fast-lane run and first tripped on the main full run.

Fix

Make the counter increment thread-safe (wrap it in a threading.Lock) so the count is exact under both the GIL and the free-threaded interpreter. Only this one test is affected; the other counter-based tests in test_metadata.py / test_overview.py / test_visibility.py assert a single non-concurrent call (== 1) and cannot lose an update.

Notes

Surfaced by the 3.14t lane added in #3360. The job is allowed-failure (continue-on-error), so the overall main run still concludes success, but the red job is noise until this is fixed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtestsTest coverage and parity

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions