From 601efab4bef3180cd5c387717588fbec2a0dd1fe Mon Sep 17 00:00:00 2001 From: bxwllzz Date: Sat, 27 Dec 2025 18:22:59 +0800 Subject: [PATCH] Fix EINTR handling in read() and readdir() loops - read(): POSIX specifies that errno is undefined when read() return values are >= 0. The previous retry logic had bugs: When read() returns 0 (EOF), the loop condition checked errno before the return value. Since errno might be stale from a previous call, this could trigger a false retry on EOF. - readdir(): When readdir() reaches the end of directory, it returns NULL without modifying errno. Setting errno=0 before the loop caused an infinite loop. --- include/ghc/filesystem.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index 89fccfd..a14b88f 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -3977,7 +3977,7 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options } ssize_t br, bw; while (true) { - do { br = ::read(in, buffer.data(), buffer.size()); } while(errno == EINTR && !br); + do { br = ::read(in, buffer.data(), buffer.size()); } while(br == -1 && errno == EINTR); if(!br) { break; } @@ -5722,8 +5722,10 @@ public: bool skip; do { skip = false; - errno = 0; - do { _entry = ::readdir(_dir); } while(errno == EINTR && !_entry); + do { + errno = 0; + _entry = ::readdir(_dir); + } while (errno == EINTR && !_entry); if (_entry) { _dir_entry._path = _base; _dir_entry._path.append_name(_entry->d_name);