Skip to content

Ferrum development journal · Part 19 of 19

Asynchronous I/O and the Bytes a Cancelled Write Keeps

The latest verified candidate passes focused 64-bit read and write profiles on both pipe routes. The tests caught real EOF, completion-block, and cancellation-accounting mistakes.

A file operation doesn't always finish before the function returns. The application may need to keep running, wait for an event, or cancel the request later. That means the port has to preserve the request's data and ownership until completion, even if the caller closes a handle or changes its memory in the meantime.

The latest verified 64-bit candidate now passes focused read and write profiles on both the shared named-FIFO and private-pipe routes. The tests check pending operations, completion events, file waits, cancellation, duplicate and last-handle close behavior, and protection against writing into a freed and reused read buffer.

Several real mistakes came out of those tests. One Darwin FIFO route didn't report peer closure through the readiness mechanisms first tried. Another review, using Wine's Windows conformance tests, showed that the native NT call should leave the caller's completion block unchanged while the request is pending. The earlier synthetic expectation had been wrong, so both the implementation and the test contract needed correction.

The write-cancellation bug was especially concrete. A large write had already sent a prefix of its data to the peer. Cancelling it produced a completion that claimed zero bytes had transferred. The receiver disagreed: it had the exact bytes. The correction keeps the host-accepted byte count for cancelled writes, and the test compares that count with the full prefix actually received.

The host engine passes 20 cases in each of two builds: normal ARM64 and ThreadSanitizer, for 40 case runs. The Windows write profiles pass on both routes, and the existing read profiles were repeated on that exact rebuilt driver. These are functional results for the tested profiles, not performance numbers or a complete Windows asynchronous-I/O claim.

The next 32-bit bridge has a different requirement: its completion block is eight bytes, and its addresses belong to the guest window. An owned completion target is proposed so the worker won't retain temporary thunk-stack storage. That proposal is still uncompiled, unreviewed, and unadopted. It doesn't belong in the passing-results column yet.

OVERLAPPED I/O, completion ports, guest-thread callbacks, lifetime races, and broader regressions remain open. So do full Windows application and game sessions, Intel Mac framework integration, the graphical launcher workflow, and signed clean-machine distribution. The latest tested code remains a development candidate rather than the adopted product baseline.

What I want to keep from this increment is the way the evidence got better. We checked what the receiver actually received, preserved the old failing result, and reran related behavior on the fixed build. That's useful progress we can build on without bringing back a completion percentage the project can't support.

Ferrum development journal

View the journal

Live19 entries so farUpdated New (19 entries updated in the last 14 days)

  1. Part 1Bringing FEX to macOS: The First Windows ProgramDevelopment work: Aug 5 – 7, 2026Updated , new
  2. Part 2From Return Values to Pixels and SoundDevelopment work: Aug 8 – 11, 2026Updated , new
  3. Part 3Building More of the Windows RuntimeDevelopment work: Aug 12 – 18, 2026Updated , new
  4. Part 4Following a Game Through Its Opening VideoDevelopment work: Aug 19 – 20, 2026Updated , new
  5. Part 5Installers, Saves, Fonts, and the Parts Around the GameDevelopment work: Aug 21 – 22, 2026Updated , new
  6. Part 6Game Progress and Measuring the Right ThingDevelopment work: Aug 23 – 27, 2026Updated , new
  7. Part 7Building the 32-Bit Graphics PathDevelopment work: Aug 28 – Sep 1, 2026Updated , new
  8. Part 8Making Memory, Files, and Graphics State AgreeDevelopment work: Sep 2 – 3, 2026Updated , new
  9. Part 9DirectX 12, Shader Caches, and the Steam Startup WorkDevelopment work: Sep 4 – 6, 2026Updated , new
  10. Part 10Working on Presentation and Controller InputDevelopment work: Sep 7 – 12, 2026Updated , new
  11. Part 11A Launcher and a Freeze That Wasn't the PresenterDevelopment work: Sep 15 – 17, 2026Updated , new
  12. Part 12Portal Reaches a Command Stream, With the Frame Still AheadDevelopment work: Sep 23 – 26, 2026Updated , new
  13. Part 13Correcting the Ferrum Progress ReportDevelopment work: Oct 2, 2026Updated , new
  14. Part 14Recovering the Project and Resuming Real TestsDevelopment work: Oct 5, 2026Updated , new
  15. Part 15Making Memory Protection and Lifetime Tests More UsefulDevelopment work: Oct 6 – 9, 2026Updated , new
  16. Part 16Getting Wine's Real 32-Bit Startup to RunDevelopment work: Oct 9 – 11, 2026Updated , new
  17. Part 17Making the Launcher Own Its Storage and ProcessesDevelopment work: Oct 11, 2026Updated , new
  18. Part 18A Real Archive Roundtrip and Better File BehaviorDevelopment work: Oct 11, 2026Updated , new
  19. Part 19Asynchronous I/O and the Bytes a Cancelled Write KeepsDevelopment work: Oct 11, 2026Updated , new

Arrow keys move through the results, Enter opens one, Command or Control with Enter opens it in a new tab. Tab and Shift+Tab change which kind of results are shown.