diff options
Diffstat (limited to 'zencore/filesystem.cpp')
| -rw-r--r-- | zencore/filesystem.cpp | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/zencore/filesystem.cpp b/zencore/filesystem.cpp index 5e376ffda..0aa478404 100644 --- a/zencore/filesystem.cpp +++ b/zencore/filesystem.cpp @@ -947,7 +947,28 @@ PathFromHandle(void* NativeHandle) return std::filesystem::path(); } - const DWORD RequiredLengthIncludingNul = GetFinalPathNameByHandleW(NativeHandle, nullptr, 0, FILE_NAME_OPENED); + auto GetFinalPathNameByHandleWRetry = [](HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags) -> DWORD { + while (true) + { + DWORD Res = GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags); + if (Res == 0) + { + DWORD LastError = zen::GetLastError(); + // Under heavy concurrent loads we might get access denied on a file handle while trying to get path name. + // Retry if that is the case. + if (LastError != ERROR_ACCESS_DENIED) + { + ThrowSystemError(LastError, fmt::format("failed to get path from file handle {}", hFile)); + } + // Retry + continue; + } + ZEN_ASSERT(Res != 1); // We don't accept empty path names + return Res; + } + }; + + DWORD RequiredLengthIncludingNul = GetFinalPathNameByHandleWRetry(NativeHandle, nullptr, 0, FILE_NAME_OPENED); if (RequiredLengthIncludingNul == 0) { ThrowLastError(fmt::format("failed to get path from file handle {}", NativeHandle)); @@ -956,8 +977,7 @@ PathFromHandle(void* NativeHandle) std::wstring FullPath; FullPath.resize(RequiredLengthIncludingNul - 1); - const DWORD FinalLength = GetFinalPathNameByHandleW(NativeHandle, FullPath.data(), RequiredLengthIncludingNul, FILE_NAME_OPENED); - + const DWORD FinalLength = GetFinalPathNameByHandleWRetry(NativeHandle, FullPath.data(), RequiredLengthIncludingNul, FILE_NAME_OPENED); ZEN_UNUSED(FinalLength); return FullPath; |