Skip to content

Commit 35bdc25

Browse files
committed
Addendum to 2ab6fe0: Fix file lock issue during updater extract process
1 parent 1375c89 commit 35bdc25

2 files changed

Lines changed: 30 additions & 4 deletions

File tree

Client/loader/Install.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "Dialogs.h"
1515
#include "Main.h"
1616
#include <unrar/dll.hpp>
17+
#include <algorithm>
1718
#include <optional>
1819
#include <memory>
1920
#include <filesystem>
@@ -237,7 +238,7 @@ static void GetArchiveFilesInDirectory(const SString& directory, std::vector<Man
237238
}
238239

239240
/**
240-
* @brief Terminates every process locking a file with the user's consent.
241+
* @brief Tries to clear file locks by terminating other processes with the user's consent.
241242
* @param absolutePath The path to the file to check
242243
* @param displayName Name of the file in the user prompt
243244
* @return True if the file is not locked (anymore), false otherwise
@@ -246,9 +247,27 @@ static bool TerminateFileLockingProcesses(const SString& absolutePath, const SSt
246247
{
247248
WString filePath(absolutePath);
248249
std::vector<DWORD> processIds = GetProcessListUsingFile(filePath);
250+
const DWORD currentProcessId = GetCurrentProcessId();
251+
252+
const auto RemoveCurrentProcessId = [&]() {
253+
const auto newEnd = std::remove(processIds.begin(), processIds.end(), currentProcessId);
254+
const bool removedCurrentProcess = newEnd != processIds.end();
255+
processIds.erase(newEnd, processIds.end());
256+
return removedCurrentProcess;
257+
};
258+
259+
const auto FailOnCurrentProcessLock = [&]() {
260+
AddReportLog(5055, SString("TerminateFileLockingProcesses: current process %lu is locking '%s'", currentProcessId, absolutePath.c_str()));
261+
return false;
262+
};
249263

250264
while (true)
251265
{
266+
const bool currentProcessLocksFile = RemoveCurrentProcessId();
267+
268+
if (currentProcessLocksFile)
269+
return FailOnCurrentProcessLock();
270+
252271
if (processIds.empty())
253272
return true;
254273

@@ -274,6 +293,10 @@ static bool TerminateFileLockingProcesses(const SString& absolutePath, const SSt
274293
"MTA: San Andreas", MB_CANCELTRYCONTINUE | MB_ICONQUESTION | MB_TOPMOST);
275294

276295
processIds = GetProcessListUsingFile(filePath);
296+
const bool currentProcessLocksFileAfterPrompt = RemoveCurrentProcessId();
297+
298+
if (currentProcessLocksFileAfterPrompt)
299+
return FailOnCurrentProcessLock();
277300

278301
if (processIds.empty())
279302
return true;
@@ -644,7 +667,8 @@ static int RunInstall()
644667
if (files.empty())
645668
return 0;
646669

647-
// Check if any executable or library is locked by any process and terminate it with the user's consent.
670+
// Binary replacements can fail after backup work has started, so clear blocking locks before
671+
// any file copy starts.
648672
for (const InstallableFile& file : files)
649673
{
650674
if (file.relativePath.EndsWithI(".exe") || file.relativePath.EndsWithI(".dll"))

Client/loader/Main.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,10 @@ namespace
148148
// Start logging.....now
149149
BeginEventLog();
150150

151-
// Start localization if possible
152-
InitLocalization(false);
151+
// A temp updater shouldnt load the install root's core.dll before RunInstall;
152+
// the localization module stays loaded and would block replacement.
153+
if (!IsTemporaryUpdateLaunchPath(GetLaunchPath()))
154+
InitLocalization(false);
153155

154156
// Handle commands from the installer
155157
HandleSpecialLaunchOptions();

0 commit comments

Comments
 (0)