You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A tray run whose UI thread or OnStop hangs can only be stopped with SIGKILL: every repeated Ctrl+C, SIGTERM and SIGHUP is cancelled and does nothing #63
Once a tray host exists, ShutdownSignals.RequestShutdown returns true for every signal, which cancels the signal's default handling. It ignores what the host's own RequestShutdown returned (TrayApp/Tray/ShutdownSignals.cs L63-L72):
_=running.RequestShutdown();returntrue;
TrayApplication.RequestShutdown posts Shutdown to the UI thread only the first time (TrayApplication.cs L255-L262). The test ARepeatedSignal_IsStillTakenButPostsNoSecondShutdown locks this behaviour in.
So if the posted shutdown can't complete, nothing short of SIGKILL ends the process. The shutdown can stall in two ways:
The UI thread is blocked in tool code. For example, a toggle setter or command waiting on D-Bus, a hung network mount, or a lock.
The tool's OnStop hangs.OnStop runs on the UI thread, from OnExit → Dispose.
Every normal way to stop the process is swallowed:
Ctrl+C in the launching terminal
kill
systemctl stop (systemd waits out its stop timeout, then sends SIGKILL)
closing the terminal
A terminal user has to go and find the PID.
ConsoleRunner has a smaller version of the same gap. Its SIGTERM registration (ConsoleRunner.cs L66) is still active while OnStop runs in the finally, so a SIGTERM sent during a hung OnStop is also cancelled.
Repro (ran)
A process holds a ShutdownSignals over a real TrayApplication whose dispatcher is never pumped, which stands in for a busy UI thread. It then receives TERM, TERM, INT, INT and HUP, 0.5 s apart:
pid 2974 ready
still alive after TERM,TERM,INT,INT,HUP
... Killed (exit=137, only kill -9 worked)
Why it matters
The #21 fix exists so that a signal ends the run through OnStop and the preference flush. It shouldn't also take away the user's last way to stop a wedged tool. The usual CLI convention is that a second Ctrl+C or SIGTERM forces the exit. Before #52/#55, Ctrl+C still killed a stuck tray, so this is arguably a regression.
Suggested fix
In ShutdownSignals.RequestShutdown, return running.RequestShutdown(). Then only the first signal is cancelled, and a repeated signal gets its default handling and ends the process.
If that's too abrupt, a softer option is a grace period: cancel repeats for N seconds after the first signal, then let them through.
In ConsoleRunner, apply the same rule: either drop the SIGTERM registration before OnStop runs, or let repeated signals through.
Acceptance criteria
After the first signal has posted a shutdown, a second Ctrl+C, SIGTERM or SIGHUP is not cancelled.
ARepeatedSignal_IsStillTakenButPostsNoSecondShutdown is updated to reflect this.
scripts/check-tray-signals.sh still passes: a single signal still ends the run through OnStop with exit code 0.
Activity