feat(daemon): deliver stop reliably and never kill the node unasked
Closing the wallet sent "stop" at most twice, gated on a getinfo probe that needs the daemon's cs_main, then killed the node after 20 s (Windows) or 30 s (POSIX) whether or not stop had arrived. A node busy with an hour-long witness rebuild therefore never got stop, was killed mid- rebuild, and replayed everything since its last flush on every start. Delivery (src/daemon/stop_delivery.h, RPCClient::open/trySendStop): - stop goes over a dedicated client with no probe, so it never waits on rpc_'s lock or a cs_main-bound getinfo - every attempt is classified, and StopDeliveryPolicy decides the next: Accepted / 503 = delivered; Queued (reply timeout) is resent at most every 30 s; QueueFull / not listening are retried every 1.5 s; a refusal after we were heard means the node is shutting down; a 401 on our own node tries the next credential source - POSIX: a group SIGTERM goes out as soon as an attempt fails, which bypasses the HTTP queue entirely Waiting (DaemonController::executeDaemonStop, pure, virtual-clock tested): - never kills on its own. Quitting waits as long as the node needs; the shutdown screen offers "Close wallet — leave node running" after 3 s, and "Kill node (unsafe)" (confirmed) only once stop was delivered and the node showed no CPU/I-O progress for ~10 min outside a rebuild - other callers (restart, rescan, reinstall, switch, ...) wait up to 120 s, let go once the app starts quitting, and keep watching a node that is still running; wallet switch refuses to go ahead then - EmbeddedDaemon gains stop-session primitives (beginStop, pollOwnedProcess, signalGracefulStop, forceKillOwnedProcess, ownedResourceUsage over the Linux process group / Windows handle, endStop) and only one stop session runs at a time - the Force Quit button and its stall heuristic are gone; "Leave running" aborts a pending stop attempt and closes at once Verified against the fake daemon with the real GUI: closing mid-rebuild now delivers stop (or SIGTERM 2 ms after a queue-full refusal) and the node exits cleanly after its rebuild, where it was SIGKILLed before. The shutdown screen, its "Leave running" button and the idle Kill offer (after ~11 min) were checked by screenshot. New strings are English- only for now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -587,6 +587,19 @@ void I18n::loadBuiltinEnglish()
|
||||
strings_["force_quit_confirm_title"] = "Force Quit?";
|
||||
strings_["force_quit_confirm_msg"] = "This will immediately kill the daemon without a clean shutdown.\nThis may corrupt the blockchain index and require a resync.";
|
||||
strings_["force_quit_yes"] = "Force Quit";
|
||||
// Stopping the node on quit: deliver stop, wait, never kill unasked (translations: S10 batch)
|
||||
strings_["shutdown_leave_running"] = "Close wallet — leave node running";
|
||||
strings_["shutdown_leave_running_tip"] = "Closes the wallet now. The node keeps running and finishes shutting down on its own; nothing is lost.";
|
||||
strings_["shutdown_kill_node"] = "Kill node (unsafe)";
|
||||
strings_["shutdown_kill_node_tip"] = "Ends the node at once. Anything it has not saved is lost, and its next start replays the blocks since its last save.";
|
||||
strings_["shutdown_kill_confirm_title"] = "Kill the node?";
|
||||
strings_["shutdown_kill_confirm_msg"] = "The node has shown no CPU or disk activity for a long time and may be stuck.\nKilling it loses everything it has not saved; its next start can take much longer.";
|
||||
strings_["shutdown_kill_confirm_yes"] = "Kill node";
|
||||
strings_["shutdown_stop_asking"] = "Asking the node to stop…";
|
||||
strings_["shutdown_stop_queued"] = "The node has the stop request but is busy — it will stop when it can";
|
||||
strings_["shutdown_stop_delivered"] = "The node is shutting down and saving its state";
|
||||
strings_["shutdown_stop_cpu_suffix"] = " · CPU %d%%";
|
||||
strings_["shutdown_stop_idle"] = "No CPU or disk activity for %d min — the node may be stuck";
|
||||
strings_["reduce_motion"] = "Reduce Motion";
|
||||
strings_["tt_reduce_motion"] = "Disable animated transitions and balance lerp for accessibility";
|
||||
strings_["ago"] = "ago";
|
||||
|
||||
Reference in New Issue
Block a user