diff --git a/src/app_network.cpp b/src/app_network.cpp index b97b86e..823b4c3 100644 --- a/src/app_network.cpp +++ b/src/app_network.cpp @@ -1137,21 +1137,18 @@ void App::switchToWallet(const std::string& walletFile, bool stopDaemonConfirmed // as owned (stop/isRunning/exit behave normally for the next switch and app exit). wallet_switch_phase_.store(static_cast(WalletSwitchPhase::Starting)); if (daemon_controller_) daemon_controller_->clearExternalDaemonDetected(); - // Retry the start. Right after the old node exits, its datadir lock can linger for a few - // seconds (the process is gone but the OS/BDB lock isn't released yet), so the first start - // hits "Cannot obtain a lock on data directory" and exits within the grace below. Retry — - // with the CORRECT -wallet, since active_wallet_file isn't reverted until we give up — until - // one survives (valid launch stays alive while it loads the block index/rescans, ~30-60s). - for (int attempt = 0; attempt < 6 && !ok && !shutting_down_; ++attempt) { - if (attempt > 0) std::this_thread::sleep_for(std::chrono::milliseconds(2000)); // let the lock release - if (daemon_controller_) daemon_controller_->resetCrashCount(); // retry lock-crashes aren't real - if (needRescan && daemon_controller_) daemon_controller_->setRescanOnNextStart(true); // one-shot; re-arm each try - if (shutting_down_) { ok = true; break; } - if (!startEmbeddedDaemon()) continue; // couldn't spawn (port busy) — back off + retry - std::this_thread::sleep_for(std::chrono::milliseconds(1500)); // grace: a datadir-lock crash exits within this - ok = shutting_down_ || isEmbeddedDaemonRunning(); + if (needRescan && daemon_controller_) daemon_controller_->setRescanOnNextStart(true); + // Start ONCE. Do NOT retry-spawn: a second start while the first is still shutting down leaves + // two dragonxd holding wallet.dat against each other (BDB "Failed to rename … Error"). The + // stopDaemonForWalletSwitch() wait already ensured the old node's process is gone, so a valid + // wallet opens cleanly; a bad/corrupt wallet exits during init and we revert. + ok = shutting_down_ ? true : startEmbeddedDaemon(); + // A missing/corrupt wallet makes dragonxd exit during init — confirm the process survived a + // moment; if not, the wallet is bad. (A valid launch keeps the process alive while it syncs.) + if (ok && !shutting_down_) { + std::this_thread::sleep_for(std::chrono::milliseconds(1500)); + if (!isEmbeddedDaemonRunning()) ok = false; } - if (ok && daemon_controller_) daemon_controller_->resetCrashCount(); // clean slate for the survivor // Process is up and staying up — now waiting for RPC to answer (onConnected closes the modal). if (ok) wallet_switch_phase_.store(static_cast(WalletSwitchPhase::Reconnecting)); } diff --git a/src/daemon/embedded_daemon.cpp b/src/daemon/embedded_daemon.cpp index 17f2593..b334e99 100644 --- a/src/daemon/embedded_daemon.cpp +++ b/src/daemon/embedded_daemon.cpp @@ -683,18 +683,25 @@ static DWORD findProcessByName(const char* name) { HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (snap == INVALID_HANDLE_VALUE) return 0; - - PROCESSENTRY32 entry; + + // Use the explicit WIDE Toolhelp API + a wide compare so this is correct regardless of the UNICODE + // macro. (The non-suffixed PROCESSENTRY32/Process32First map to the wide variants when UNICODE is + // defined, in which case szExeFile is WCHAR[] and an ANSI _stricmp would compare garbage and NEVER + // match — silently making findProcessByName a no-op that returns 0 for a running process.) + wchar_t wname[MAX_PATH]; + if (MultiByteToWideChar(CP_ACP, 0, name, -1, wname, MAX_PATH) == 0) { CloseHandle(snap); return 0; } + + PROCESSENTRY32W entry; entry.dwSize = sizeof(entry); - + DWORD pid = 0; - if (Process32First(snap, &entry)) { + if (Process32FirstW(snap, &entry)) { do { - if (_stricmp(entry.szExeFile, name) == 0) { + if (lstrcmpiW(entry.szExeFile, wname) == 0) { // Win32 case-insensitive wide compare pid = entry.th32ProcessID; break; } - } while (Process32Next(snap, &entry)); + } while (Process32NextW(snap, &entry)); } CloseHandle(snap); return pid;