Repository navigation
gfx_display: stop display threads without waiting on the main thread - #376
Merged
Merged
Conversation
…m main Closing the window on macOS hung iris. main stops the machine, which joins each graphics board's display thread, and that thread ends by releasing its renderer's GL context. glutin runs that release on the main thread, which is the thread waiting in the join, so neither can go on. iris never exited and the disk overlay's sector list was never saved. Every board ended its display thread with its own call to the renderer's stop: REX3 (Indy, Indigo2), GR2, the IMPACT board (Indigo2 IP28 and the Octane) and the O2's GBE. DisplayStop is now the one place that decides it. A stop asked for by a thread named "main" means the process is ending and the window is gone, so the display thread leaves the renderer alone; that stop is final. A stop from any other thread (a reset) still releases it on the thread that owns the context, so the next start sets it up afresh. GfxDisplay has an accessor for the helper, so a new board is pointed at it; nothing makes a board call it. The O2 requests it from its drop, since its stop leaves the display thread running. GR2 now records the request before it clears its running flag, so the display thread cannot end between the two. The test builds one machine per display family (Newport on an Indy, GR2 on an Indigo2, IMPACT on an Octane, the O2's GBE) and puts a renderer in its display whose stop waits for the main thread. A machine is stopped from a thread named reset, where the renderer must still be released, started again, and stopped from a thread named main, which never answers: that stop must return. The O2's display thread ends only when the machine is dropped, so it gets a machine for each. Each test in this file works in a directory of its own, and the REX3 shape corpus it saves goes to a temp file rather than the home directory. Newport shows nothing until a video mode is programmed, so its configuration selects one rather than wait for a guest to do it. Without the change all four main-thread stops hang.
Stopping a machine joined the graphics board first (the Octane stopped its devices in reverse start order, and the board starts last; the Indy and Indigo2 stopped REX3, the IMPACT board and GR2 before HPC3). A graphics stop waits on a display thread, and that wait is the one that can fail to end. When it did, everything stopped after it never ran. That is not the disk flush. The disk controllers' stops only join their workers, and the flush that follows the stop in the main thread's stop-and-flush is skipped whenever the stop does not return, whatever the order. What the reorder keeps is the work the stops themselves do: HPC3's stop saves the RTC NVRAM and the EEPROM, IOC3 writes its NVRAM out, and disk commands still in flight complete. The board now stops last, on the Octane (stop and drop) and on the Indy and Indigo2. The tests tear down a started machine's display with a renderer that notes whether a disk controller is still running at that moment: HPC3 on the Indy, the ISP1040s and IOC3 on the Octane. Each first checks that those controllers are running before the stop, so a machine that stopped starting them would fail rather than pass without testing anything. Both fail with the old order. The Octane's Ethernet controller is not checked; it has no public running state. The Indy test keeps its REX3 shape corpus out of the home directory.
jamesbraid
marked this pull request as draft
October 31, 2026 21:15
jamesbraid
marked this pull request as ready for review
October 31, 2026 21:25
jamesbraid
marked this pull request as draft
October 31, 2026 21:27
jamesbraid
force-pushed
the
display-stop-deadlock
branch
2 times, most recently
from
October 31, 2026 22:30
8696cec to
c528316
Compare
jamesbraid
marked this pull request as ready for review
October 31, 2026 22:33
Contributor
|
@techomancer cool. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On macOS, closing the window hung iris for good.
mainstops the machine, which joins each board's display thread. That thread ended withrenderer.stop(), and glutin'smake_not_currentdispatches synchronously to the main thread, which is blocked in the join. Nothing past that ran, including saving the disks, so overlay writes were lost too.Every board had it: REX3 (both heads), GR2, IMPACT on the Indigo2 and Octane, and the O2's display through its
Drop.gfx_display::DisplayStopis a small helper each board holds. A stop records whether it came from the thread named "main" (std has no is-main-thread test; Rust names the main thread, and a test on Linux can stand in for it), and if so the display thread leaves the renderer alone instead of tearing it down. A stop from any other thread (a reset, a snapshot load) still releases the context on its own thread.GfxDisplay::display_stop()points a new board at the helper; nothing forces it to call it. A main-thread stop is final; the doc says so.One test builds one machine per display family (Newport on an Indy, GR2 on an Indigo2, IMPACT on an Octane, the O2's GBE) and gives each a renderer whose
stopneeds the main thread. Each machine is stopped from a thread named "reset" (the renderer must still be released), started again, and stopped from a thread named "main": that stop must return. The O2 gets a machine for each stop. Without the fix all four main-thread stops hang. Order tests check the Octane stops its SCSI controllers and IOC3, and the Indy its HPC3, before the graphics board, after checking they were running. The tests each use a directory of their own and keep the REX3 shape corpus out of$HOME. Tested on Linux with a renderer that behaves like macOS; not run on a Mac.