On Linux, the interactive runner can hang indefinitely after the SDL frontend has already closed.
I reproduced this while testing MetroidPrimeHuntersRecomp against ndsrecomp commit 46b12e6c18dea47f87d2c1f98c3054149dcbca5d.
Observed behavior after exiting normally with Esc:
[sdl] closed after 1731 presented frames
The window closes, but the process never exits and has to be interrupted manually.
While the process was hung, the main thread was waiting on a futex and the debug pump thread was blocked in accept():
PID TID STAT WCHAN
... ... S<l+ futex_wait
... ... S<l+ inet_csk_accept
... ... S<l+ futex_wait
The play-mode debug listener was also still present:
LISTEN 0 1 127.0.0.1:19842 0.0.0.0:*
debug_pump_stop() currently sets the shutdown flag and closes the listening socket before joining the pump thread:
g_pump_shutdown.store(true, std::memory_order_relaxed);
CLOSESOCK(g_pump_listener);
g_pump_listener = INVALID_SOCKET;
...
if (g_pump_thread.joinable()) g_pump_thread.join();
On Linux, closing the listener from another thread did not wake the blocking accept() in this reproduction, so the join never completed.
As a local test, I explicitly shut down the listening socket before closing it:
#ifdef _WIN32
shutdown(g_pump_listener, SD_BOTH);
#else
shutdown(g_pump_listener, SHUT_RDWR);
#endif
CLOSESOCK(g_pump_listener);
With that change, the same test exits cleanly:
[sdl] closed after 627 presented frames
runner exit=0
So explicitly shutting down the listener appears to reliably unblock the pump thread before joining it.
On Linux, the interactive runner can hang indefinitely after the SDL frontend has already closed.
I reproduced this while testing MetroidPrimeHuntersRecomp against ndsrecomp commit
46b12e6c18dea47f87d2c1f98c3054149dcbca5d.Observed behavior after exiting normally with Esc:
The window closes, but the process never exits and has to be interrupted manually.
While the process was hung, the main thread was waiting on a futex and the debug pump thread was blocked in
accept():The play-mode debug listener was also still present:
debug_pump_stop()currently sets the shutdown flag and closes the listening socket before joining the pump thread:On Linux, closing the listener from another thread did not wake the blocking
accept()in this reproduction, so the join never completed.As a local test, I explicitly shut down the listening socket before closing it:
With that change, the same test exits cleanly:
So explicitly shutting down the listener appears to reliably unblock the pump thread before joining it.