fix(wallet): route switch stop by process-handle ownership, not the external latch
Live logs showed the app usually just DIRECT-CONNECTS to an already-running dragonxd (config found → connect; EmbeddedDaemon::start() never called). Two consequences broke the switch: no process handle, and externalDaemonDetected() stays false (it's only latched inside start()). So a direct-connected node was treated as "owned" → stopEmbeddedDaemon() → an autoDetectConfig() temp RPC stop that never reached the daemon → the node never stopped → the ~40s port poll timed out → "the running node didn't release its connection in time" revert. Gate on the real ownership signal — whether we hold a live process handle (isEmbeddedDaemonRunning()) — instead of the unreliable externalDaemonDetected(): - stopDaemonForWalletSwitch: owned (we spawned it) → stopEmbeddedDaemon() with SIGTERM/SIGKILL; NOT owned (adopted or direct-connect, no handle) → RPC "stop" over the exact creds we're connected with (saved_config_), which is guaranteed to reach our node. Then the unchanged port-free poll. - switchToWallet confirm gate: show "Stop the running node?" when connected to a node this session didn't spawn (state_.connected && !isEmbeddedDaemonRunning()). - Fixes beginAdoptSeedWallet's direct-connect case identically (shared helper). Adversarially verified (6/6): ownership signal, saved_config_ delivery incl. cookie auth, foreign-daemon safety, confirm gate, seed-adopt, re-ownership/revert. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1056,11 +1056,11 @@ void App::switchToWallet(const std::string& walletFile, bool stopDaemonConfirmed
|
||||
ui::Notifications::instance().warning("Finish or cancel the pending send before switching wallets.");
|
||||
return;
|
||||
}
|
||||
// The node we'd restart may be one this session ADOPTED — a dragonxd already running when the wallet
|
||||
// launched (left running by "keep node running", or started by the user). Switching must stop+restart
|
||||
// it on the new wallet, so confirm first rather than killing a node the user may have kept up on
|
||||
// purpose. (An owned node we started this session restarts silently, as before.)
|
||||
if (!stopDaemonConfirmed && daemon_controller_ && daemon_controller_->externalDaemonDetected()) {
|
||||
// If we're connected to a node this session did NOT spawn (no live process handle — it was left
|
||||
// running by "keep node running", started by the user, or we just direct-connected to a config-provided
|
||||
// one), confirm before stopping it: switching must stop+restart it on the new wallet, but the user may
|
||||
// have kept it running on purpose. A node we started ourselves (handle held) restarts silently.
|
||||
if (!stopDaemonConfirmed && state_.connected && !isEmbeddedDaemonRunning()) {
|
||||
pending_switch_wallet_file_ = walletFile;
|
||||
show_switch_stop_daemon_confirm_ = true;
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user