fix(wallet): wait for the old node to fully exit before restarting on switch
After the stop, the switch started the replacement dragonxd too early — while the old (direct-connected, unowned) node was still doing a slow graceful shutdown (~70s; its network threads block on peer TLS timeouts) and holding the DATADIR LOCK. The replacement couldn't acquire the lock, failed repeatedly, and the crash-wedge left it stuck "starting". Root cause: the readiness poll used isRpcPortInUse(), which on Windows is a connect() probe that reads "free" the moment the daemon stops ACCEPTING RPC — early in shutdown, long before the process exits and releases the datadir. - EmbeddedDaemon::isDaemonProcessRunning(): true while any dragonxd process is alive (Windows findProcessByName; Linux /proc/<pid>/comm scan; macOS port fallback) — reflects the PROCESS, not just RPC acceptance. - stopDaemonForWalletSwitch: for an UNOWNED node (no handle), after the RPC stop wait until BOTH the port is free AND isDaemonProcessRunning() is false, bounded ~120s (or ~5s if the stop couldn't be sent). Owned nodes are unchanged (stopEmbeddedDaemon() blocks for exit via the handle). - Switch notification reworded to set the up-to-a-minute expectation (60s toast). daemon_restarting_ stays set across the wait so the connect loop can't spawn a competing daemon. Adversarially verified 6/6; fixes the seed-adopt path too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1104,7 +1104,9 @@ void App::switchToWallet(const std::string& walletFile, bool stopDaemonConfirmed
|
||||
// can't surface (or sign outgoing chat) under the new wallet. It re-provisions from the new
|
||||
// wallet's seed once it connects. onDisconnected alone doesn't cover chat.
|
||||
resetChatSession();
|
||||
ui::Notifications::instance().info("Switching wallet — the node will restart…");
|
||||
ui::Notifications::instance().info(
|
||||
"Switching wallet — stopping the node and restarting on the new wallet. "
|
||||
"A graceful shutdown can take up to a minute.", 60.0f);
|
||||
|
||||
async_tasks_.submit("Switch wallet", [this, needRescan](const util::AsyncTaskManager::Token&) {
|
||||
bool ok = false;
|
||||
|
||||
Reference in New Issue
Block a user