Skip to content

test_io_shared: Replace sync/skip workarounds with barriers - #982

Merged
eschnett merged 4 commits into
masterfrom
eschnett/test-io-shared-flakiness-c88603
Sep 11, 2026
Merged

eschnett merged 4 commits into
masterfrom
eschnett/test-io-shared-flakiness-c88603

Conversation

@eschnett

@eschnett eschnett commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

test_io_shared: Replace sync/skip workarounds with the barriers actually needed

The flakiness (#555 on Windows, #879 on macOS, and the Ubuntu failures seen in #926) was a data race in the test itself, not a library bug.

MPI_File_get_position_shared is not collective, but every other shared file pointer call in this test moves the pointer: write_ordered and read_ordered increment it, seek_shared and set_view reset it. ROMIO and OMPIO both perform the reset on rank 0 (ROMIO's set_view: on every rank that has the hidden .shfp file open) before their internal barrier, and write_ordered increments the counter on rank 0 as soon as rank 0 enters the call. So a fast rank entering the next operation clobbers the pointer while a slow rank is still inside @test get_position_shared(fh) == .... That is exactly the 0 == 10 / 0 == 3 reported in the issues.

The fix is a plain MPI.Barrier after each block of position checks and before the next shared-pointer operation. MPI_File_sync only flushes file data (ROMIO keeps the pointer in a side file, OMPIO in shared memory) and plays no role; the old sync/Barrier/sync wrapper only helped through its embedded Barrier. With atomicity enabled the header data needs no sync either, only ordering.

The vendor detection and the Apple/MPICH/Windows skip= clauses were masking the same race and are removed. Reproduced locally on macOS with MPICH 4.3.1, MPICH_jll 5.x, OpenMPI_jll 5.0.10 and MPItrampoline_jll: 30-60% failure rate without the barriers, 0 failures in 80 runs with them.

Fixes #555, fixes #879.

(Thumbs pressed that this works!)

…lly needed

The flakiness (#555 on Windows, #879 on macOS, and the Ubuntu failures
seen in #926) was a data race in the test itself, not a library bug.

MPI_File_get_position_shared is not collective, but every other shared
file pointer call in this test moves the pointer: write_ordered and
read_ordered increment it, seek_shared and set_view reset it. ROMIO and
OMPIO both perform the reset on rank 0 (ROMIO's set_view: on every rank
that has the hidden .shfp file open) *before* their internal barrier, and
write_ordered increments the counter on rank 0 as soon as rank 0 enters
the call. So a fast rank entering the next operation clobbers the pointer
while a slow rank is still inside `@test get_position_shared(fh) == ...`.
That is exactly the `0 == 10` / `0 == 3` reported in the issues.

The fix is a plain MPI.Barrier after each block of position checks and
before the next shared-pointer operation. MPI_File_sync only flushes file
data (ROMIO keeps the pointer in a side file, OMPIO in shared memory) and
plays no role; the old sync/Barrier/sync wrapper only helped through its
embedded Barrier. With atomicity enabled the header data needs no sync
either, only ordering.

The vendor detection and the Apple/MPICH/Windows `skip=` clauses were
masking the same race and are removed. Reproduced locally on macOS with
MPICH 4.3.1, MPICH_jll 5.x, OpenMPI_jll 5.0.10 and MPItrampoline_jll:
30-60% failure rate without the barriers, 0 failures in 80 runs with them.

Fixes #555, fixes #879.
@vchuravy
vchuravy force-pushed the eschnett/test-io-shared-flakiness-c88603 branch from d6cbfbc to 07fbedb Compare September 9, 2026 10:35
@vchuravy

vchuravy commented Sep 9, 2026

Copy link
Copy Markdown
Member

Still seems to have some issues on Windows?

@eschnett

eschnett commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

I hope #984 will help on Windows.

`test_io.jl` wrote collectively, called `MPI_File_sync`, and then had rank 0
read the whole file at once, with nothing ordering that read after the other
ranks' writes. In the default non-atomic mode the standard requires writer
sync, a barrier, and reader sync before another process's data is visible.
Without the barrier, a rank 0 that runs ahead reads zeros:

    Test Failed at test/test_io.jl:24
      Evaluated: Int64[1 0 0 0; 1 0 0 0] == [1 2 3 4; 1 2 3 4]

as seen on the Windows nightly x86 job of #982. Because the failing rank's
`atexit` hook then called `MPI_Finalize` while the other ranks waited in the
next barrier, the job deadlocked until the 20-minute timeout instead of
failing fast. The same missing barrier preceded the collective read after
rank sz-1's overwrite; both places now use sync, barrier, sync.

`test_io_subarray.jl` needs no change: every rank reads back only the bytes
it wrote itself through the same file handle, which the standard guarantees
to be consistent without synchronization. A comment records this so nobody
adds barriers there by analogy.

Verified with 4 ranks: MPICH 4.3.1, MPICH_jll 5.0.1, OpenMPI_jll 5.0.10 and
MPItrampoline_jll, 10 repetitions each, no failures.
Comment thread test/test_io.jl Outdated
@eschnett
eschnett merged commit 32e8e5b into master Sep 11, 2026
62 checks passed
@eschnett
eschnett deleted the eschnett/test-io-shared-flakiness-c88603 branch September 11, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI] Intermittent failure in test_io_shared test on macOS Spurios test failures on Windows for get_position_shared

2 participants