Skip to content

fix: serialize pretty-mode build progress output under OpenMP#1296

Open
krystophny wants to merge 1 commit into
fortran-lang:mainfrom
krystophny:fix/parallel-progress-race
Open

fix: serialize pretty-mode build progress output under OpenMP#1296
krystophny wants to merge 1 commit into
fortran-lang:mainfrom
krystophny:fix/parallel-progress-race

Conversation

@krystophny

@krystophny krystophny commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Wrap each target's compound pretty-mode status update in a named
    critical(fpm_progress) so it is atomic against other threads
  • Make the n_complete counter coherent: !$omp atomic capture on increment
    and !$omp atomic read on use, replacing an unnamed critical write paired
    with an unsynchronized read
  • Plain mode (off a TTY, including CI) is untouched: each line is a single
    self-contained write, so per-write atomicity already suffices

Context

Each target's pretty-mode update is a compound of two console_t writes, and
console_update_line moves the terminal cursor relative to the tracked line
count. On main the two writes sit in separate unnamed !$omp critical
regions, so another worker thread can interleave its own output between them,
change n_line, and invalidate the cursor arithmetic. The result is garbled
progress on an interactive terminal under -fopenmp.

Merge order

Independent PRs (any order):

Stacked chain (merge in order):

  1. Fortran compiles via argv (feat: exec Fortran compiles via argv (posix_spawn/CreateProcess) #1299)
  2. Parallel link/archive via argv (feat: run link and archive in parallel via argv spawn #1300)
  3. C/C++ compiles via argv (feat: exec C/C++ compiles via argv, close the shell-fork gap #1301)

Fork-safety fix:

After the above:

Verification

$ fpm build --flag -fopenmp
[100%] Project compiled successfully.

$ fpm test --flag -fopenmp
TALLY;TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
PASSED: all 35 tests passed

The defect is a non-deterministic data race that only manifests in pretty/TTY
mode under multiple OpenMP threads, so there is no stable automated reproducer.
The before-state is visible in the source on main: the compound update spans
two separate unnamed critical regions in src/fpm_backend_output.f90, and
console_update_line in src/fpm_backend_console.f90 performs cursor movement
relative to a shared, concurrently-mutated n_line.

Each target's pretty-mode (TTY) status update is a compound of two console
writes, and console_update_line steps the cursor relative to the tracked line
count. Previously the two writes sat in separate unnamed critical regions, so a
concurrent worker thread could interleave its own output between them and
invalidate the relative cursor math, corrupting the rendered progress.

Wrap each target's compound update in a named critical(fpm_progress) so it is
atomic against other threads. Plain mode (used off a TTY, in CI) is unchanged.

Also make the n_complete counter coherent: increment with atomic capture and
read with atomic read, instead of an unnamed critical write paired with an
unsynchronized read.
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.

1 participant