Fixing local matrix output interleave on windows
Problem
test_local_matrix_debug_output failed intermittently on Windows CI: console log text appeared inside ogs_local_matrix.log, byte-split mid-number.
spdlog's Windows stdout sinks cache the stdout OS HANDLE at sink creation and WriteFile() to it forever. The wheel runs OGS in-process; pytest's fd capture dup2s fd 1/2 per test, which closes the cached handle. Windows recycles handle values, so when a later CreateFile for the matrix log received the recycled value, console output was written into that file (shared file object, shared offset). On most repetitions console output was silently lost instead. Any in-process embedding that redirects fds (pytest, Jupyter, ogstools) could corrupt any file OGS opens.
Proven by instrumented CI runs: jobs 770361 (single shared file object) and 770457 (cached sink handle resolved to ogs_local_matrix.log).
Fix
Windows-only custom sink (Fd1StdoutSink) that writes via _write(_fileno(stdout), ...), resolving the target through the live CRT fd table on every write - immune to later redirection. POSIX keeps the colour sinks (their FILE*-based path is safe). Trade-off: no console colour on Windows.
Tests / result
- Hammer job: 1000/1000 repetitions passed on the previously failing runner win-vis-3-ogs (job 770465); before the fix it failed within ~30-350 repetitions (jobs 770143, 770305, 770457).
- Reproduces only with pytest fd capture enabled (1000 clean with -s, job 770356) and only on some runners - handle-allocation dependent.
Alternatives considered
- Thread-safe sink under _OPENMP (918cbb8d): ineffective - corruption is cross-stream, not a data race.
- Atomic single-write of each matrix block: reduces splitting but the console bytes still land in the wrong file.
- Running the wheel test in a subprocess: hides the defect for this test only; other embeddings stay affected.