diff options
| author | Dan Engelbrecht <[email protected]> | 2023-09-12 08:03:46 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-09-12 14:03:46 +0200 |
| commit | f463686b9621b8c744e2dcb0d018ad507716d499 (patch) | |
| tree | 7cf50625dbfe3b731131b779c6286ae9ca6423d7 /src/zencore/filesystem.cpp | |
| parent | gracefully handle errors when writing cache log (#391) (diff) | |
| download | zen-f463686b9621b8c744e2dcb0d018ad507716d499.tar.xz zen-f463686b9621b8c744e2dcb0d018ad507716d499.zip | |
Make sure error logging or destructors don't throw exception when trying to get file name from handle (#393)
- Bugfix: Make sure error logging or destructors don't throw exception when trying to get file name from handle
Diffstat (limited to 'src/zencore/filesystem.cpp')
| -rw-r--r-- | src/zencore/filesystem.cpp | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/src/zencore/filesystem.cpp b/src/zencore/filesystem.cpp index 8abe5af00..b1ec14a37 100644 --- a/src/zencore/filesystem.cpp +++ b/src/zencore/filesystem.cpp @@ -1063,19 +1063,25 @@ FileSystemTraversal::TraverseFileSystem(const std::filesystem::path& RootDir, Tr closedir(Dir); #endif // ZEN_PLATFORM_WINDOWS } - std::filesystem::path -PathFromHandle(void* NativeHandle) +PathFromHandle(void* NativeHandle, std::error_code& Ec) { + if (NativeHandle == nullptr) + { + return std::filesystem::path(); + } #if ZEN_PLATFORM_WINDOWS - if (NativeHandle == nullptr || NativeHandle == INVALID_HANDLE_VALUE) + if (NativeHandle == INVALID_HANDLE_VALUE) { return std::filesystem::path(); } - auto GetFinalPathNameByHandleWRetry = [](HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags) -> DWORD { - while (true) + auto GetFinalPathNameByHandleWRetry = + [&Ec](HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags, DWORD& OutRequiredLength) -> DWORD { + size_t MaxTries = 5; + while (MaxTries > 0) { + MaxTries--; DWORD Res = GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags); if (Res == 0) { @@ -1084,22 +1090,27 @@ PathFromHandle(void* NativeHandle) // Retry if that is the case. if (LastError != ERROR_ACCESS_DENIED) { - ThrowSystemError(LastError, fmt::format("failed to get path from file handle {}", hFile)); + Sleep(2); + return LastError; } // Retry continue; } ZEN_ASSERT(Res != 1); // We don't accept empty path names - return Res; + OutRequiredLength = Res; + return ERROR_SUCCESS; } + return ERROR_ACCESS_DENIED; }; static const DWORD PathDataSize = 512; wchar_t PathData[PathDataSize]; - DWORD RequiredLengthIncludingNul = GetFinalPathNameByHandleWRetry(NativeHandle, PathData, PathDataSize, FILE_NAME_OPENED); - if (RequiredLengthIncludingNul == 0) + DWORD RequiredLengthIncludingNul = 0; + DWORD Error = GetFinalPathNameByHandleWRetry(NativeHandle, PathData, PathDataSize, FILE_NAME_OPENED, RequiredLengthIncludingNul); + if (Error != ERROR_SUCCESS) { - ThrowLastError(fmt::format("failed to get path from file handle {}", NativeHandle)); + Ec = MakeErrorCodeFromLastError(); + return std::filesystem::path(); } if (RequiredLengthIncludingNul < PathDataSize) @@ -1111,7 +1122,13 @@ PathFromHandle(void* NativeHandle) std::wstring FullPath; FullPath.resize(RequiredLengthIncludingNul - 1); - const DWORD FinalLength = GetFinalPathNameByHandleWRetry(NativeHandle, FullPath.data(), RequiredLengthIncludingNul, FILE_NAME_OPENED); + DWORD FinalLength = 0; + Error = GetFinalPathNameByHandleWRetry(NativeHandle, FullPath.data(), RequiredLengthIncludingNul, FILE_NAME_OPENED, FinalLength); + if (Error != ERROR_SUCCESS) + { + Ec = MakeErrorCodeFromLastError(); + return std::filesystem::path(); + } ZEN_UNUSED(FinalLength); return FullPath; @@ -1123,7 +1140,8 @@ PathFromHandle(void* NativeHandle) ssize_t BytesRead = readlink(Path, Link, sizeof(Link) - 1); if (BytesRead <= 0) { - return std::filesystem::path(); + Ec = MakeErrorCodeFromLastError(); + return {}; } Link[BytesRead] = '\0'; @@ -1133,13 +1151,26 @@ PathFromHandle(void* NativeHandle) char Path[MAXPATHLEN]; if (fcntl(Fd, F_GETPATH, Path) < 0) { - return std::filesystem::path(); + Ec = MakeErrorCodeFromLastError(); + return {}; } return Path; #endif // ZEN_PLATFORM_WINDOWS } +std::filesystem::path +PathFromHandle(void* NativeHandle) +{ + std::error_code Ec; + std::filesystem::path Result = PathFromHandle(NativeHandle, Ec); + if (Ec) + { + throw std::system_error(Ec, fmt::format("failed to get path from file handle '{}'", NativeHandle)); + } + return Result; +} + uint64_t FileSizeFromHandle(void* NativeHandle) { |