The rugnux thread put its result in place only after destroying the run and releasing the pinned host
memory the engines kept between them, so the end message and the writer waited for that teardown.
The result is now moved out first and a promise tells the measurement thread it can send the end
message; the run is destroyed and the pinned pool released on the rugnux thread (the same thread, so
the same CUDA device as before) beside it, and the measurement thread joins the rugnux thread at the
end of the collection, before it reports itself finished. The end message reads only rugnux_result,
a value moved out of the run (it already outlived the run), and nothing in the teardown touches it.
A run that fails still releases the waiting measurement thread.
Measured on the workstation (CLI harness doing the broker's teardown after Run): the run's destruction
0.03-0.04 s and the pinned pool release (440-540 MB) 0.08-0.10 s, so ~0.12 s off last image -> end
message on a cytochrome-C-size rotation set. Processing and outputs are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu