diff --git a/src/resources/embedded_resources.cpp b/src/resources/embedded_resources.cpp index 8ba2d56..266f0b5 100644 --- a/src/resources/embedded_resources.cpp +++ b/src/resources/embedded_resources.cpp @@ -274,8 +274,30 @@ static bool extractResource(const EmbeddedResource* res, const std::string& dest // Write file std::ofstream file(destPath, std::ios::binary); if (!file) { - DEBUG_LOGF("[ERROR] Failed to open %s for writing\n", destPath.c_str()); - return false; + // The destination may be locked because the previous daemon is still using the binary: + // Windows locks a running .exe against truncation, Linux returns ETXTBSY. Both platforms + // DO allow renaming/moving such a file — the running process keeps the moved copy — so move + // the stale binary aside and write a fresh one at the original path. + std::error_code ec; + if (std::filesystem::exists(destPath)) { + std::string sidelined = destPath + ".old"; + std::filesystem::remove(sidelined, ec); // clear any leftover from a prior swap + ec.clear(); + std::filesystem::rename(destPath, sidelined, ec); + if (!ec) { + file.clear(); + file.open(destPath, std::ios::binary); + if (file) + DEBUG_LOGF("[INFO] Replaced in-use %s (old copy moved to .old)\n", destPath.c_str()); + } else { + DEBUG_LOGF("[WARN] Could not move stale %s aside: %s\n", + destPath.c_str(), ec.message().c_str()); + } + } + if (!file) { + DEBUG_LOGF("[ERROR] Failed to open %s for writing\n", destPath.c_str()); + return false; + } } file.write(reinterpret_cast(res->data), res->size); @@ -413,7 +435,18 @@ bool extractEmbeddedResources() } } #endif - + + // Best-effort cleanup of any ".old" binaries left behind by a previous in-use replacement. + // Once the old daemon/xmrig process has exited, the file is no longer locked and removes cleanly; + // if it's still running, the remove fails harmlessly and we retry on the next startup. + { + std::error_code ec; + for (const char* name : { RESOURCE_DRAGONXD, RESOURCE_XMRIG }) { + std::filesystem::remove(daemonDir + pathSep + name + std::string(".old"), ec); + ec.clear(); + } + } + return success; }