From 4fa0d88eb91cc3853c558ba25c14e24db49f8727 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Mon, 7 Jul 2025 15:35:21 +1000 Subject: [PATCH 01/50] Fix handling of `readdir` giving `EINTR` --- src/coreclr/debug/createdump/crashinfounix.cpp | 10 +++++++++- src/coreclr/gc/unix/numasupport.cpp | 10 +++++++++- src/coreclr/hosts/corerun/corerun.hpp | 10 +++++++++- src/coreclr/tools/superpmi/mcs/verbmerge.cpp | 15 ++++++++++----- src/native/corehost/hostmisc/pal.unix.cpp | 10 +++++++++- src/native/libs/System.Native/pal_io.c | 9 +++++++-- .../pal_x509.c | 11 ++++++++++- 7 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfounix.cpp b/src/coreclr/debug/createdump/crashinfounix.cpp index b0bcb0b8c2d3b8..52d52912e30853 100644 --- a/src/coreclr/debug/createdump/crashinfounix.cpp +++ b/src/coreclr/debug/createdump/crashinfounix.cpp @@ -121,8 +121,16 @@ CrashInfo::EnumerateAndSuspendThreads() } struct dirent* entry; - while ((entry = readdir(taskDir)) != nullptr) + while (true) { + do + { + errno = 0; + entry = readdir(taskDir); + } + while (entry == nullptr && errno == EINTR); + if (entry == nullptr) break; + pid_t tid = static_cast(strtol(entry->d_name, nullptr, 10)); if (tid != 0) { diff --git a/src/coreclr/gc/unix/numasupport.cpp b/src/coreclr/gc/unix/numasupport.cpp index 17e2764f456e2d..160fd9cd201997 100644 --- a/src/coreclr/gc/unix/numasupport.cpp +++ b/src/coreclr/gc/unix/numasupport.cpp @@ -31,8 +31,16 @@ static int GetNodeNum(const char* path, bool firstOnly) dir = opendir(path); if (dir) { - while ((entry = readdir(dir)) != NULL) + while (true) { + do + { + errno = 0; + entry = readdir(dir); + } + while (entry == nullptr && errno == EINTR); + if (entry == nullptr) break; + if (strncmp(entry->d_name, "node", STRING_LENGTH("node"))) continue; diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 48e6ed4c1295e0..f0f8c27aa9631f 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -512,8 +512,16 @@ namespace pal // For all entries in the directory struct dirent* entry; - while ((entry = readdir(dir)) != nullptr) + while (true) { + do + { + errno = 0; + entry = readdir(dir); + } + while (entry == nullptr && errno == EINTR); + if (entry == nullptr) break; + #if HAVE_DIRENT_D_TYPE int dirEntryType = entry->d_type; #else diff --git a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp index e85997864188d1..e24e4657f0febe 100644 --- a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp +++ b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp @@ -277,18 +277,23 @@ int verbMerge::FilterDirectory(LPCWSTR dir, DIR* pDir = opendir(dirUtf8.c_str()); if (pDir != nullptr) { - errno = 0; - dirent *pEntry = readdir(pDir); - while (pEntry != nullptr) + dirent *pEntry; + while (true) { + do + { + errno = 0; + pEntry = readdir(pDir); + } + while (pEntry == nullptr && errno == EINTR); + if (pEntry == nullptr) break; + if ((fnmatch(searchPatternUtf8.c_str(), pEntry->d_name, 0) == 0) && filter(pEntry)) { FindData findData(pEntry->d_type, ConvertMultiByteToWideChar(pEntry->d_name)); first = new findDataList(&findData, first); ++elemCount; } - errno = 0; - pEntry = readdir(pDir); } if (errno != 0) diff --git a/src/native/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp index 6a0922ff84159b..ce0c97a890e641 100644 --- a/src/native/corehost/hostmisc/pal.unix.cpp +++ b/src/native/corehost/hostmisc/pal.unix.cpp @@ -1009,8 +1009,16 @@ static void readdir(const pal::string_t& path, const pal::string_t& pattern, boo if (dir != nullptr) { struct dirent* entry = nullptr; - while ((entry = readdir(dir)) != nullptr) + while (true) { + do + { + errno = 0; + entry = readdir(dir); + } + while (entry == nullptr && errno == EINTR); + if (entry == nullptr) break; + if (fnmatch(pattern.c_str(), entry->d_name, FNM_PATHNAME) != 0) { continue; diff --git a/src/native/libs/System.Native/pal_io.c b/src/native/libs/System.Native/pal_io.c index 74bead7dc0ada9..517ed6485cfe98 100644 --- a/src/native/libs/System.Native/pal_io.c +++ b/src/native/libs/System.Native/pal_io.c @@ -506,8 +506,13 @@ int32_t SystemNative_ReadDir(DIR* dir, DirectoryEntry* outputEntry) assert(dir != NULL); assert(outputEntry != NULL); - errno = 0; - struct dirent* entry = readdir(dir); + struct dirent* entry; + do + { + errno = 0; + entry = readdir(dir); + } + while (entry == NULL && errno == EINTR); // 0 returned with null result -> end-of-stream if (entry == NULL) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c index 2f07a3cd2da2a8..0137c45c27f95c 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c @@ -5,6 +5,7 @@ #include "../Common/pal_safecrt.h" #include +#include #include #include #include @@ -477,8 +478,16 @@ static X509* ReadNextPublicCert(DIR* dir, X509Stack* tmpStack, char* pathTmp, si assert((size_t)offset < pathTmpSize); size_t remaining = pathTmpSize - (size_t)offset; - while ((next = readdir(dir)) != NULL) + while (true) { + do + { + errno = 0; + next = readdir(dir); + } + while (next == NULL && errno == EINTR); + if (next == NULL) break; + size_t len = strnlen(next->d_name, sizeof(next->d_name)); if (len > 4 && 0 == strncasecmp(".pfx", next->d_name + len - 4, 4)) From 0049bf37bba3318ad2643ed3be09a23b605f1f4f Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Mon, 7 Jul 2025 15:41:55 +1000 Subject: [PATCH 02/50] Fix handling of `opendir` giving `EINTR` --- src/coreclr/debug/createdump/crashinfounix.cpp | 4 +++- src/coreclr/gc/unix/numasupport.cpp | 2 +- src/coreclr/hosts/corerun/corerun.hpp | 4 +++- src/coreclr/tools/superpmi/mcs/verbmerge.cpp | 4 +++- src/native/corehost/hostmisc/pal.unix.cpp | 4 +++- .../libs/System.Security.Cryptography.Native/pal_x509.c | 3 ++- 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfounix.cpp b/src/coreclr/debug/createdump/crashinfounix.cpp index 52d52912e30853..b9a7994f08a16d 100644 --- a/src/coreclr/debug/createdump/crashinfounix.cpp +++ b/src/coreclr/debug/createdump/crashinfounix.cpp @@ -113,7 +113,9 @@ CrashInfo::EnumerateAndSuspendThreads() return false; } - DIR* taskDir = opendir(taskPath); + DIR* taskDir; + while ((taskDir = opendir(taskPath)) == nullptr && errno == EINTR); + if (taskDir == nullptr) { printf_error("Problem enumerating threads: opendir(%s) FAILED %s (%d)\n", taskPath, strerror(errno), errno); diff --git a/src/coreclr/gc/unix/numasupport.cpp b/src/coreclr/gc/unix/numasupport.cpp index 160fd9cd201997..6b66b2e0868b58 100644 --- a/src/coreclr/gc/unix/numasupport.cpp +++ b/src/coreclr/gc/unix/numasupport.cpp @@ -28,7 +28,7 @@ static int GetNodeNum(const char* path, bool firstOnly) struct dirent *entry; int result = -1; - dir = opendir(path); + while ((dir = opendir(path)) == nullptr && errno == EINTR); if (dir) { while (true) diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index f0f8c27aa9631f..8c2d57fbb497b1 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -504,7 +504,9 @@ namespace pal assert(ext != nullptr); const size_t ext_len = pal::strlen(ext); - DIR* dir = opendir(directory.c_str()); + DIR* dir; + while ((dir = opendir(directory.c_str())) == nullptr && errno == EINTR); + if (dir == nullptr) return {}; diff --git a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp index e24e4657f0febe..82a405072d69c8 100644 --- a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp +++ b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp @@ -274,7 +274,9 @@ int verbMerge::FilterDirectory(LPCWSTR dir, std::string dirUtf8 = ConvertToUtf8(dir); std::string searchPatternUtf8 = ConvertToUtf8(searchPattern); - DIR* pDir = opendir(dirUtf8.c_str()); + DIR* pDir; + while ((pDir = opendir(dirUtf8.c_str())) == nullptr && errno == EINTR); + if (pDir != nullptr) { dirent *pEntry; diff --git a/src/native/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp index ce0c97a890e641..5bbb6aa5471bcc 100644 --- a/src/native/corehost/hostmisc/pal.unix.cpp +++ b/src/native/corehost/hostmisc/pal.unix.cpp @@ -1005,7 +1005,9 @@ static void readdir(const pal::string_t& path, const pal::string_t& pattern, boo std::vector& files = *list; - auto dir = opendir(path.c_str()); + DIR *dir; + while ((dir = opendir(path.c_str())) == nullptr && errno == EINTR); + if (dir != nullptr) { struct dirent* entry = nullptr; diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c index 0137c45c27f95c..53b2af5f033e3d 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c @@ -437,7 +437,8 @@ X509* CryptoNative_X509UpRef(X509* x509) static DIR* OpenUserStore(const char* storePath, char** pathTmp, size_t* pathTmpSize, char** nextFileWrite) { - DIR* trustDir = opendir(storePath); + DIR* trustDir; + while ((trustDir = opendir(storePath)) == NULL && errno == EINTR); if (trustDir == NULL) { From a9793f842724a174f476cb27b7d0efa3bc66c612 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 09:58:05 +1000 Subject: [PATCH 03/50] Ensure handling of `fcntl` giving `EINTR` is consistent - Excludes potential changes to libunwind --- src/coreclr/pal/src/file/file.cpp | 18 +++++++++++---- src/coreclr/pal/src/map/map.cpp | 2 +- src/coreclr/pal/src/synchmgr/synchmanager.cpp | 4 ++-- src/coreclr/pal/src/thread/process.cpp | 14 +++++++---- src/coreclr/pal/src/thread/threadsusp.cpp | 4 ++-- src/mono/mono/sgen/sgen-protocol.c | 15 +++++++----- src/native/eventpipe/ds-ipc-pal-socket.c | 16 +++++++++---- src/native/libs/System.Native/pal_io.c | 23 +++++++++++++------ .../libs/System.Native/pal_networking.c | 19 +++++++++------ src/native/minipal/log.c | 4 +++- src/native/minipal/random.c | 2 +- 11 files changed, 80 insertions(+), 41 deletions(-) diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 8d0cfa99f789d3..1a134abab80af0 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -612,7 +612,9 @@ CorUnix::InternalCreateFile( if ( dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING ) { #ifdef F_NOCACHE - if (-1 == fcntl(filed, F_NOCACHE, 1)) + int fcntl_result; + while (-1 == (fcntl_result = fcntl(filed, F_NOCACHE, 1)) && errno == EINTR); + if (-1 == fcntl_result) { ASSERT("Can't set F_NOCACHE; fcntl() failed. errno is %d (%s)\n", errno, strerror(errno)); @@ -635,7 +637,9 @@ CorUnix::InternalCreateFile( /* make file descriptor close-on-exec; inheritable handles will get "uncloseonexeced" in CreateProcess if they are actually being inherited*/ - if(-1 == fcntl(filed,F_SETFD, FD_CLOEXEC)) + int fcntl_result; + while (-1 == (fcntl_result = fcntl(filed,F_SETFD, FD_CLOEXEC)) && errno == EINTR); + if(-1 == fcntl_result) { ASSERT("can't set close-on-exec flag; fcntl() failed. errno is %d " "(%s)\n", errno, strerror(errno)); @@ -2166,14 +2170,18 @@ CorUnix::InternalCreatePipe( /* enable close-on-exec for both pipes; if one gets passed to CreateProcess it will be "uncloseonexeced" in order to be inherited */ - if(-1 == fcntl(readWritePipeDes[0],F_SETFD,FD_CLOEXEC)) + int fcntl_result; + while (-1 == (fcntl_result = fcntl(readWritePipeDes[0],F_SETFD,FD_CLOEXEC)) && errno == EINTR); + if(-1 == fcntl_result) { ASSERT("can't set close-on-exec flag; fcntl() failed. errno is %d " "(%s)\n", errno, strerror(errno)); palError = ERROR_INTERNAL_ERROR; goto InternalCreatePipeExit; } - if(-1 == fcntl(readWritePipeDes[1],F_SETFD,FD_CLOEXEC)) + int fcntl_result; + while (-1 == (fcntl_result = fcntl(readWritePipeDes[1],F_SETFD,FD_CLOEXEC)) && errno == EINTR); + if(-1 == fcntl_result) { ASSERT("can't set close-on-exec flag; fcntl() failed. errno is %d " "(%s)\n", errno, strerror(errno)); @@ -2416,7 +2424,7 @@ static HANDLE init_std_handle(HANDLE * pStd, FILE *stream) /* duplicate the FILE *, so that we can fclose() in FILECloseHandle without closing the original */ - new_fd = fcntl(fileno(stream), F_DUPFD_CLOEXEC, 0); // dup, but with CLOEXEC + while (-1 == (new_fd = fcntl(fileno(stream), F_DUPFD_CLOEXEC, 0)) && errno == EINTR); // dup, but with CLOEXEC if(-1 == new_fd) { ERROR("dup() failed; errno is %d (%s)\n", errno, strerror(errno)); diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 8900ccd1058c01..19d09d8da497d0 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -467,7 +467,7 @@ CorUnix::InternalCreateFileMapping( // information, though... // - UnixFd = fcntl(pFileLocalData->unix_fd, F_DUPFD_CLOEXEC, 0); // dup, but with CLOEXEC + while (-1 == (UnixFd = fcntl(pFileLocalData->unix_fd, F_DUPFD_CLOEXEC, 0)) && errno == EINTR); // dup, but with CLOEXEC if (-1 == UnixFd) { ERROR( "Unable to duplicate the Unix file descriptor!\n" ); diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index 0665df179caa04..ecec3d003c8ffd 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -2778,8 +2778,8 @@ namespace CorUnix goto CPP_exit; } #if !HAVE_PIPE2 - fcntl(rgiPipe[0], F_SETFD, FD_CLOEXEC); // make pipe non-inheritable, if possible - fcntl(rgiPipe[1], F_SETFD, FD_CLOEXEC); + while (-1 == fcntl(rgiPipe[0], F_SETFD, FD_CLOEXEC) && errno == EINTR); // make pipe non-inheritable, if possible + while (-1 == fcntl(rgiPipe[1], F_SETFD, FD_CLOEXEC) && errno == EINTR); #endif // !HAVE_PIPE2 #endif // !CORECLR diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index c56cc0637dcd2f..5bb553b2b4b8f7 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -464,7 +464,7 @@ PrepareStandardHandle( goto PrepareStandardHandleExit; } - iError = fcntl(pLocalData->unix_fd, F_SETFD, 0); + while (-1 == (iError = fcntl(pLocalData->unix_fd, F_SETFD, 0)) && errno == EINTR); if (-1 == iError) { ERROR("Unable to remove close-on-exec for file (errno %i)\n", errno); @@ -1015,7 +1015,9 @@ CorUnix::InternalCreateProcess( their close-on-exec flag */ if (NULL != pobjFileIn) { - if(-1 == fcntl(iFdIn, F_SETFD, 1)) + int fcntl_result; + while (-1 == (fcntl_result = fcntl(iFdIn, F_SETFD, 1)) && errno == EINTR); + if(-1 == fcntl_result) { WARN("couldn't restore close-on-exec flag to stdin descriptor! " "errno is %d (%s)\n", errno, strerror(errno)); @@ -1025,7 +1027,9 @@ CorUnix::InternalCreateProcess( if (NULL != pobjFileOut) { - if(-1 == fcntl(iFdOut, F_SETFD, 1)) + int fcntl_result; + while (-1 == (fcntl_result = fcntl(iFdOut, F_SETFD, 1)) && errno == EINTR); + if(-1 == fcntl_result) { WARN("couldn't restore close-on-exec flag to stdout descriptor! " "errno is %d (%s)\n", errno, strerror(errno)); @@ -1035,7 +1039,9 @@ CorUnix::InternalCreateProcess( if (NULL != pobjFileErr) { - if(-1 == fcntl(iFdErr, F_SETFD, 1)) + int fcntl_result; + while (-1 == (fcntl_result = fcntl(iFdErr, F_SETFD, 1)) && errno == EINTR); + if(-1 == fcntl_result) { WARN("couldn't restore close-on-exec flag to stderr descriptor! " "errno is %d (%s)\n", errno, strerror(errno)); diff --git a/src/coreclr/pal/src/thread/threadsusp.cpp b/src/coreclr/pal/src/thread/threadsusp.cpp index 867f46b3fa38f2..ec6cea6c2c1d86 100644 --- a/src/coreclr/pal/src/thread/threadsusp.cpp +++ b/src/coreclr/pal/src/thread/threadsusp.cpp @@ -86,8 +86,8 @@ CThreadSuspensionInfo::InternalSuspendNewThreadFromData( return ERROR_NOT_ENOUGH_MEMORY; } #if !HAVE_PIPE2 - fcntl(pipe_descs[0], F_SETFD, FD_CLOEXEC); // make pipe non-inheritable, if possible - fcntl(pipe_descs[1], F_SETFD, FD_CLOEXEC); + while (-1 == fcntl(pipe_descs[0], F_SETFD, FD_CLOEXEC) && errno == EINTR); // make pipe non-inheritable, if possible + while (-1 == fcntl(pipe_descs[1], F_SETFD, FD_CLOEXEC) && errno == EINTR); #endif // !HAVE_PIPE2 // [0] is the read end of the pipe, and [1] is the write end. diff --git a/src/mono/mono/sgen/sgen-protocol.c b/src/mono/mono/sgen/sgen-protocol.c index 7c7543cd4292c8..aea3acca131c4c 100644 --- a/src/mono/mono/sgen/sgen-protocol.c +++ b/src/mono/mono/sgen/sgen-protocol.c @@ -106,14 +106,17 @@ binary_protocol_open_file (gboolean assert_on_failure) if (binary_protocol_file == -1) { if (errno != EINTR) break; /* Failed */ + } else { #ifdef F_SETLK - } else if (fcntl (binary_protocol_file, F_SETLK, &lock) == -1) { - /* The lock for the file is already taken. Fail */ - close (binary_protocol_file); - binary_protocol_file = -1; - break; + int fcntl_result; + while (-1 == (fcntl_result = fcntl (binary_protocol_file, F_SETLK, &lock)) && errno == EINTR); + if (fcntl_result == -1) { + /* The lock for the file is already taken. Fail */ + close (binary_protocol_file); + binary_protocol_file = -1; + break; + } #endif - } else { /* We have acquired the lock. Truncate the file */ int ret; while ((ret = ftruncate (binary_protocol_file, 0)) < 0 && errno == EINTR); diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index 4a16fb5f81f253..a05084851fe33c 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -345,7 +345,10 @@ ipc_socket_create_uds (DiagnosticsIpc *ipc) new_socket = socket (ipc->server_address_family, socket_type, 0); #ifndef SOCK_CLOEXEC if (new_socket != DS_IPC_INVALID_SOCKET) - fcntl (new_socket, F_SETFD, FD_CLOEXEC); // ignore any failures; this is best effort + { + int fcntl_result; + while (-1 == (fcntl_result = fcntl (new_socket, F_SETFD, FD_CLOEXEC)) && errno == EINTR); // ignore any failures; this is best effort + } #endif // SOCK_CLOEXEC DS_EXIT_BLOCKING_PAL_SECTION; return new_socket; @@ -375,7 +378,7 @@ ipc_socket_create_tcp (DiagnosticsIpc *ipc) if (new_socket != DS_IPC_INVALID_SOCKET) { #ifndef SOCK_CLOEXEC #ifndef HOST_WIN32 - fcntl (new_socket, F_SETFD, FD_CLOEXEC); // ignore any failures; this is best effort + while (-1 == fcntl (new_socket, F_SETFD, FD_CLOEXEC) && errno == EINTR); // ignore any failures; this is best effort #endif // HOST_WIN32 #endif // SOCK_CLOEXEC int option_value = 1; @@ -459,9 +462,12 @@ ipc_socket_set_blocking ( u_long blocking_mode = blocking ? 0 : 1; result = ioctlsocket (s, FIONBIO, &blocking_mode); #else - result = fcntl (s, F_GETFL, 0); + while (-1 == (result = fcntl (s, F_GETFL, 0)) && errno == EINTR); if (result != -1) - result = fcntl (s, F_SETFL, blocking ? (result & (~O_NONBLOCK)) : (result | (O_NONBLOCK))); + { + int value = blocking ? (result & (~O_NONBLOCK)) : (result | (O_NONBLOCK)); + while (-1 == (result = fcntl (s, F_SETFL, value)) && errno == EINTR); + } #endif DS_EXIT_BLOCKING_PAL_SECTION; return result; @@ -564,7 +570,7 @@ ipc_socket_accept ( if (client_socket != -1) { // ignore any failures; this is best effort - fcntl (client_socket, F_SETFD, FD_CLOEXEC); + while (-1 == fcntl (client_socket, F_SETFD, FD_CLOEXEC) && errno == EINTR); } #endif #endif diff --git a/src/native/libs/System.Native/pal_io.c b/src/native/libs/System.Native/pal_io.c index 517ed6485cfe98..1b38ba4ce5711e 100644 --- a/src/native/libs/System.Native/pal_io.c +++ b/src/native/libs/System.Native/pal_io.c @@ -335,7 +335,7 @@ intptr_t SystemNative_Open(const char* path, int32_t flags, int32_t mode) #if !HAVE_O_CLOEXEC if (old_flags & PAL_O_CLOEXEC) { - fcntl(result, F_SETFD, FD_CLOEXEC); + while (-1 == fcntl(result, F_SETFD, FD_CLOEXEC) && errno == EINTR); } #endif return result; @@ -353,8 +353,11 @@ intptr_t SystemNative_Dup(intptr_t oldfd) while ((result = fcntl(ToFileDescriptor(oldfd), F_DUPFD_CLOEXEC, 0)) < 0 && errno == EINTR); #elif HAVE_F_DUPFD while ((result = fcntl(ToFileDescriptor(oldfd), F_DUPFD, 0)) < 0 && errno == EINTR); - // do CLOEXEC here too - fcntl(result, F_SETFD, FD_CLOEXEC); + if (result != -1) + { + // do CLOEXEC here too + while (-1 == fcntl(result, F_SETFD, FD_CLOEXEC) && errno == EINTR); + } #else // The main use cases for dup are setting up the classic Unix dance of setting up file descriptors in advance of performing a fork. Since WASI has no fork, these don't apply. // https://github.com/bytecodealliance/wasmtime/blob/b2fefe77148582a9b8013e34fe5808ada82b6efc/docs/WASI-rationale.md#why-no-dup @@ -618,7 +621,9 @@ int32_t SystemNative_FcntlSetFD(intptr_t fd, int32_t flags) int32_t SystemNative_FcntlGetFD(intptr_t fd) { - return fcntl(ToFileDescriptor(fd), F_GETFD); + int result; + while (-1 == (result = fcntl(ToFileDescriptor(fd), F_GETFD)) && errno == EINTR); + return result; } int32_t SystemNative_FcntlCanGetSetPipeSz(void) @@ -660,7 +665,8 @@ int32_t SystemNative_FcntlSetIsNonBlocking(intptr_t fd, int32_t isNonBlocking) { int fileDescriptor = ToFileDescriptor(fd); - int flags = fcntl(fileDescriptor, F_GETFL); + int flags; + while (-1 == (flags = fcntl(fileDescriptor, F_GETFL)) && errno == EINTR); if (flags == -1) { return -1; @@ -675,7 +681,9 @@ int32_t SystemNative_FcntlSetIsNonBlocking(intptr_t fd, int32_t isNonBlocking) flags |= O_NONBLOCK; } - return fcntl(fileDescriptor, F_SETFL, flags); + int result; + while (-1 == (result = fcntl(fileDescriptor, F_SETFL, flags)) && errno == EINTR); + return result; } int32_t SystemNative_FcntlGetIsNonBlocking(intptr_t fd, int32_t* isNonBlocking) @@ -685,7 +693,8 @@ int32_t SystemNative_FcntlGetIsNonBlocking(intptr_t fd, int32_t* isNonBlocking) return Error_EFAULT; } - int flags = fcntl(ToFileDescriptor(fd), F_GETFL); + int flags; + while (-1 == (flags = fcntl(ToFileDescriptor(fd), F_GETFL)) && errno == EINTR); if (flags == -1) { *isNonBlocking = 0; diff --git a/src/native/libs/System.Native/pal_networking.c b/src/native/libs/System.Native/pal_networking.c index ed3c90d6d6c14e..e1a4f35f19d19f 100644 --- a/src/native/libs/System.Native/pal_networking.c +++ b/src/native/libs/System.Native/pal_networking.c @@ -1713,13 +1713,18 @@ int32_t SystemNative_Accept(intptr_t socket, uint8_t* socketAddress, int32_t* so #if defined(FD_CLOEXEC) // macOS does not have accept4 but it can set _CLOEXEC on descriptor. // Unlike accept4 it is not atomic and the fd can leak child process. - if ((accepted != -1) && fcntl(accepted, F_SETFD, FD_CLOEXEC) != 0) + if (accepted != -1) { - // Preserve and return errno from fcntl. close() may reset errno to OK. - int oldErrno = errno; - close(accepted); - accepted = -1; - errno = oldErrno; + int fcntl_result; + while (-1 == (fcntl_result = fcntl(accepted, F_SETFD, FD_CLOEXEC)) && errno == EINTR); + if (fcntl_result != 0) + { + // Preserve and return errno from fcntl. close() may reset errno to OK. + int oldErrno = errno; + close(accepted); + accepted = -1; + errno = oldErrno; + } } #endif #if !defined(__linux__) @@ -2839,7 +2844,7 @@ int32_t SystemNative_Socket(int32_t addressFamily, int32_t socketType, int32_t p } #ifndef SOCK_CLOEXEC - fcntl(ToFileDescriptor(*createdSocket), F_SETFD, FD_CLOEXEC); // ignore any failures; this is best effort + while (-1 == fcntl(ToFileDescriptor(*createdSocket), F_SETFD, FD_CLOEXEC) && errno == EINTR); // ignore any failures; this is best effort #endif return Error_SUCCESS; } diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index d639111a59ddf9..efab8437411548 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -270,7 +270,9 @@ static ssize_t write_file(minipal_log_flags flags, const char* msg, size_t bytes #include static int sync_file(minipal_log_flags flags) { - if (fcntl(fileno(get_std_file(flags)), F_FULLFSYNC) != -1) + int result; + while (-1 == (result = fcntl(fileno(get_std_file(flags)), F_FULLFSYNC)) && errno == EINTR); + if (result != -1) return 0; return errno; diff --git a/src/native/minipal/random.c b/src/native/minipal/random.c index 3c2b33ac7463b0..40573b6096f697 100644 --- a/src/native/minipal/random.c +++ b/src/native/minipal/random.c @@ -115,7 +115,7 @@ int32_t minipal_get_cryptographically_secure_random_bytes(uint8_t* buffer, int32 fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); #else fd = open("/dev/urandom", O_RDONLY); - fcntl(fd, F_SETFD, FD_CLOEXEC); + while (-1 == fcntl(fd, F_SETFD, FD_CLOEXEC) && errno == EINTR); #endif } while ((fd == -1) && (errno == EINTR)); From ec7282282a0c5e2e3aa86199ffb3350002e83ef2 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 10:02:09 +1000 Subject: [PATCH 04/50] Ensure handling of `fsync` giving `EINTR` is consistent --- src/coreclr/pal/src/misc/perfjitdump.cpp | 5 +++-- src/native/minipal/log.c | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index b9afb95a574052..9a851125208299 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -5,6 +5,7 @@ #include "pal/palinternal.h" #include "pal/dbgmsg.h" +#include #include #if defined(__linux__) || defined(__APPLE__) @@ -222,7 +223,7 @@ struct PerfJitDumpState if (result == -1) return FatalError(); - result = fsync(fd); + while (-1 == (result = fsync(fd)) && errno == EINTR); if (result == -1) return FatalError(); @@ -348,7 +349,7 @@ struct PerfJitDumpState mmapAddr = MAP_FAILED; - result = fsync(fd); + while (-1 == (result = fsync(fd)) && errno == EINTR); if (result == -1) return FatalError(); diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index efab8437411548..f1b41a98030552 100644 --- a/src/native/minipal/log.c +++ b/src/native/minipal/log.c @@ -281,7 +281,9 @@ static int sync_file(minipal_log_flags flags) #include static int sync_file(minipal_log_flags flags) { - if (fsync(fileno(get_std_file(flags))) == 0) + int result; + while (-1 == (result = fsync(fileno(get_std_file(flags)))) && errno == EINTR); + if (result == 0) return 0; return errno; From 7e0a56d23ae8571762eea657abebadaabfa8dfc5 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 10:06:23 +1000 Subject: [PATCH 05/50] Ensure handling of `chmod` giving `EINTR` is consistent --- .../tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/coreclr/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp b/src/coreclr/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp index be2017c6d523bb..d1853128e95fc0 100644 --- a/src/coreclr/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp +++ b/src/coreclr/pal/tests/palsuite/file_io/WriteFile/test1/WriteFile.cpp @@ -74,8 +74,9 @@ PALTEST(file_io_WriteFile_test1_paltest_writefile_test1, "file_io/WriteFile/test Fail("WriteFile: ERROR[%ld] -> Unable to create file \"%s\".\n", last_error, szReadOnlyFile); } - - if ((last_error = chmod(szReadOnlyFile, S_IRUSR | S_IRGRP | S_IROTH)) != 0) + + while (-1 == (last_error = chmod(szReadOnlyFile, S_IRUSR | S_IRGRP | S_IROTH)) && errno == EINTR); + if (last_error != 0) { Trace("WriteFile: ERROR[%ld] -> Unable to make the file read-only.\n", last_error); do_cleanup_WriteFile_test1(); @@ -101,7 +102,8 @@ PALTEST(file_io_WriteFile_test1_paltest_writefile_test1, "file_io/WriteFile/test } //To delete file need to make it normal - if ((last_error = chmod(szReadOnlyFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) != 0) + while (-1 == (last_error = chmod(szReadOnlyFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) && errno == EINTR); + if (last_error != 0) { Fail("WriteFile: ERROR[%ld] -> Unable to make the file attribute NORMAL.\n", last_error); From d6a331ae15c87a677f51f9cdff2e765c6c48f7cd Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 10:12:56 +1000 Subject: [PATCH 06/50] Ensure handling of `ftruncate` giving `EINTR` is consistent --- src/coreclr/minipal/Unix/doublemapping.cpp | 8 ++++++-- src/coreclr/pal/src/map/map.cpp | 2 +- .../tests/palsuite/threading/NamedMutex/test1/nopal.cpp | 4 +++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/coreclr/minipal/Unix/doublemapping.cpp b/src/coreclr/minipal/Unix/doublemapping.cpp index 4a2516bea58484..2380e5ae41d4a2 100644 --- a/src/coreclr/minipal/Unix/doublemapping.cpp +++ b/src/coreclr/minipal/Unix/doublemapping.cpp @@ -82,7 +82,9 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu } #endif - if (ftruncate(fd, MaxDoubleMappedSize) == -1) + int ftruncate_result; + while (-1 == (ftruncate_result = ftruncate(fd, MaxDoubleMappedSize)) && errno == EINTR); + if (ftruncate_result == -1) { close(fd); return false; @@ -390,7 +392,9 @@ TemplateThunkMappingData *InitializeTemplateThunkMappingData(void* pTemplate) if (fd != -1) { off_t maxFileSize = MAX_TEMPLATE_THUNK_TYPES * 0x10000; // The largest page size we support currently is 64KB. - if (ftruncate(fd, maxFileSize) == -1) // Reserve a decent size chunk of logical memory for these things. + int ftruncate_result; + while (-1 == (ftruncate_result = ftruncate(fd, maxFileSize)) && errno == EINTR); + if (ftruncate_result == -1) // Reserve a decent size chunk of logical memory for these things. { close(fd); } diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 19d09d8da497d0..8e8ee22046dc9c 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -1489,7 +1489,7 @@ static PAL_ERROR MAPGrowLocalFile( INT UnixFD, off_t NewSize ) /* ftruncate is a standard function, but the behavior of enlarging files is non-standard. So I will try to enlarge a file, and if that fails try the less efficient way.*/ - TruncateRetVal = ftruncate( UnixFD, NewSize ); + while (-1 == (TruncateRetVal = ftruncate( UnixFD, NewSize )) && errno == EINTR); fstat( UnixFD, &FileInfo ); if ( TruncateRetVal != 0 || FileInfo.st_size != NewSize ) diff --git a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp index 435f53108b9300..4f8cdc93d136cf 100644 --- a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp +++ b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp @@ -71,7 +71,9 @@ bool WriteHeaderInfo(const char *path, bool currentUserOnly, char sharedMemoryTy } *fdRef = fd; - if (ftruncate(fd, getpagesize()) != 0) + int result; + while (-1 == (result = ftruncate(fd, getpagesize())) && errno == EINTR); + if (result != 0) return false; if (lseek(fd, 0, SEEK_SET) != 0) return false; From aa891ddd65432d012497d1b9199e56551d028994 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 10:15:31 +1000 Subject: [PATCH 07/50] Ensure handling of `flock` giving `EINTR` is consistent --- src/coreclr/pal/src/sharedmemory/sharedmemory.cpp | 3 ++- .../pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 5d12b850f9b9bc..381a364e178358 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -722,7 +722,8 @@ bool SharedMemoryHelpers::TryAcquireFileLock(SharedMemorySystemCallErrors *error while (true) { - int flockResult = flock(fileDescriptor, operation); + int flockResult; + while (-1 == (flockResult = flock(fileDescriptor, operation)) && errno == EINTR); if (flockResult == 0) { return true; diff --git a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp index 4f8cdc93d136cf..6a7bac56c2146c 100644 --- a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp +++ b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp @@ -83,5 +83,7 @@ bool WriteHeaderInfo(const char *path, bool currentUserOnly, char sharedMemoryTy if (write(fd, buffer, ARRAY_SIZE(buffer)) != ARRAY_SIZE(buffer)) return false; - return flock(fd, LOCK_SH | LOCK_NB) == 0; + int flock_result; + while (-1 == (flock_result = flock(fd, LOCK_SH | LOCK_NB)) && errno == EINTR); + return flock_result == 0; } From b159416808fd7a5962fcc9f87f217d9866b351e1 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 10:23:34 +1000 Subject: [PATCH 08/50] Ensure handling of `poll` giving `EINTR` is consistent I skipped those which were already in infinite loops anyway --- src/coreclr/pal/src/synchmgr/synchmanager.cpp | 6 +++--- src/mono/mono/component/debugger-poll.c | 3 ++- src/native/libs/System.Native/pal_console.c | 4 +++- src/native/libs/System.Native/pal_console_wasi.c | 4 +++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index ecec3d003c8ffd..51b3ddff78ee32 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -1849,7 +1849,7 @@ namespace CorUnix Poll.events = POLLIN; Poll.revents = 0; - iRet = poll(&Poll, 1, iTimeout); + while (-1 == (iRet = poll(&Poll, 1, iTimeout)) && errno == EINTR); TRACE("Woken up from poll() with ret=%d [iTimeout=%d]\n", iRet, iTimeout); @@ -3111,7 +3111,7 @@ namespace CorUnix ERROR("Failed creating thread synchronization mutex [error=%d (%s)]\n", iRet, strerror(iRet)); if (EAGAIN == iRet && MaxUnavailableResourceRetries >= ++iEagains) { - poll(NULL, 0, std::min(100,10*iEagains)); + while (-1 == poll(NULL, 0, std::min(100,10*iEagains)) && errno == EINTR); goto Mutex_retry; } else if (ENOMEM == iRet) @@ -3137,7 +3137,7 @@ namespace CorUnix "[error=%d (%s)]\n", iRet, strerror(iRet)); if (EAGAIN == iRet && MaxUnavailableResourceRetries >= ++iEagains) { - poll(NULL, 0, std::min(100,10*iEagains)); + while (-1 == poll(NULL, 0, std::min(100,10*iEagains)) && errno == EINTR); goto Cond_retry; } else if (ENOMEM == iRet) diff --git a/src/mono/mono/component/debugger-poll.c b/src/mono/mono/component/debugger-poll.c index b914c7bdde05e2..0e7f4ee96a43dc 100644 --- a/src/mono/mono/component/debugger-poll.c +++ b/src/mono/mono/component/debugger-poll.c @@ -42,7 +42,8 @@ mono_poll_can_add (mono_pollfd *ufds, unsigned int nfds, int fd) int mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout) { - return poll (ufds, nfds, timeout); + int result; + while (-1 == (result = poll (ufds, nfds, timeout)) && errno == EINTR); } #else diff --git a/src/native/libs/System.Native/pal_console.c b/src/native/libs/System.Native/pal_console.c index b51e16c0bbc271..aedd40ac8fe60a 100644 --- a/src/native/libs/System.Native/pal_console.c +++ b/src/native/libs/System.Native/pal_console.c @@ -370,7 +370,9 @@ int32_t SystemNative_StdinReady(void) { SystemNative_InitializeConsoleBeforeRead(/* minChars */ 1, /* decisecondsTimeout */ 0); struct pollfd fd = { .fd = STDIN_FILENO, .events = POLLIN }; - int rv = poll(&fd, 1, 0) > 0 ? 1 : 0; + int poll_result; + while (-1 == (poll_result = poll(&fd, 1, 0)) && errno == EINTR); + int rv = poll_result > 0 ? 1 : 0; SystemNative_UninitializeConsoleAfterRead(); return rv; } diff --git a/src/native/libs/System.Native/pal_console_wasi.c b/src/native/libs/System.Native/pal_console_wasi.c index be7aaf888294f7..0fc44d266b89e3 100644 --- a/src/native/libs/System.Native/pal_console_wasi.c +++ b/src/native/libs/System.Native/pal_console_wasi.c @@ -79,7 +79,9 @@ void SystemNative_GetControlCharacters( int32_t SystemNative_StdinReady(void) { struct pollfd fd = { .fd = STDIN_FILENO, .events = POLLIN }; - int rv = poll(&fd, 1, 0) > 0 ? 1 : 0; + int poll_result; + while (-1 == (poll_result = poll(&fd, 1, 0)) && errno == EINTR); + int rv = poll_result > 0 ? 1 : 0; return rv; } From 143b964c0ae922a97186d9ba68ea48f258e65a77 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 10:30:27 +1000 Subject: [PATCH 09/50] Ensure handling of `waitpid` giving `EINTR` is consistent - Excludes potential changes to libunwind --- src/coreclr/debug/createdump/crashinfounix.cpp | 4 ++-- src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp | 3 ++- src/coreclr/pal/src/thread/process.cpp | 3 ++- src/mono/mono/mini/mini-posix.c | 2 +- src/native/libs/System.Native/pal_process.c | 2 +- src/native/watchdog/watchdog.cpp | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfounix.cpp b/src/coreclr/debug/createdump/crashinfounix.cpp index b9a7994f08a16d..32bb7ff8a15112 100644 --- a/src/coreclr/debug/createdump/crashinfounix.cpp +++ b/src/coreclr/debug/createdump/crashinfounix.cpp @@ -84,7 +84,7 @@ CrashInfo::CleanupAndResumeProcess() if (ptrace(PTRACE_DETACH, thread->Tid(), nullptr, nullptr) != -1) { int waitStatus; - waitpid(thread->Tid(), &waitStatus, __WALL); + while (-1 == waitpid(thread->Tid(), &waitStatus, __WALL) && errno == EINTR); } } if (m_fdMem != -1) @@ -140,7 +140,7 @@ CrashInfo::EnumerateAndSuspendThreads() if (ptrace(PTRACE_ATTACH, tid, nullptr, nullptr) != -1) { int waitStatus; - waitpid(tid, &waitStatus, __WALL); + while (-1 == waitpid(tid, &waitStatus, __WALL) && errno == EINTR); } else { diff --git a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp index 552dba78dd68d1..48c977e4df7923 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp @@ -292,7 +292,8 @@ CreateCrashDump( // Parent waits until the child process is done int wstatus = 0; - int result = waitpid(childpid, &wstatus, 0); + int result; + while (-1 == (result = waitpid(childpid, &wstatus, 0)) && errno == EINTR); if (result != childpid) { fprintf(stderr, "Problem waiting for createdump: waitpid() FAILED result %d wstatus %08x errno %s (%d)\n", diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 5bb553b2b4b8f7..2af7748f4dc694 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -2303,7 +2303,8 @@ PROCCreateCrashDump( // Parent waits until the child process is done int wstatus = 0; - int result = waitpid(childpid, &wstatus, 0); + int result; + while (-1 == (result = waitpid(childpid, &wstatus, 0)) && errno == EINTR); if (result != childpid) { fprintf(stderr, "Problem waiting for createdump: waitpid() FAILED result %d wstatus %08x errno %s (%d)\n", diff --git a/src/mono/mono/mini/mini-posix.c b/src/mono/mono/mini/mini-posix.c index 4c36fd6b3ffeea..f67fbeaed83c0f 100644 --- a/src/mono/mono/mini/mini-posix.c +++ b/src/mono/mono/mini/mini-posix.c @@ -874,7 +874,7 @@ dump_native_stacktrace (const char *signal, MonoContext *mctx) _exit (1); } else if (need_to_fork && pid > 0) { int status; - waitpid (pid, &status, 0); + while (-1 == waitpid (pid, &status, 0) && errno == EINTR); } else { // If we can't fork, do as little as possible before exiting } diff --git a/src/native/libs/System.Native/pal_process.c b/src/native/libs/System.Native/pal_process.c index fa5e522c36205e..1e01eb22c238c4 100644 --- a/src/native/libs/System.Native/pal_process.c +++ b/src/native/libs/System.Native/pal_process.c @@ -487,7 +487,7 @@ done:; if (processId > 0) { int status; - waitpid(processId, &status, 0); + while (-1 == waitpid(processId, &status, 0) && errno == EINTR); } *stdinFd = -1; diff --git a/src/native/watchdog/watchdog.cpp b/src/native/watchdog/watchdog.cpp index 2ab508a5fb53c8..572957259d9b2a 100644 --- a/src/native/watchdog/watchdog.cpp +++ b/src/native/watchdog/watchdog.cpp @@ -113,7 +113,7 @@ int run_timed_process(const long timeout_ms, const int proc_argc, const char *pr do { // Instructions for the parent process! - wait_code = waitpid(child_pid, &child_status, WNOHANG); + while (-1 == (wait_code = waitpid(child_pid, &child_status, WNOHANG)) && errno == EINTR); if (wait_code == -1) return EINVAL; From 42f82c97936f610ea67f8ccbd9b22e3f66ae00e3 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 10:35:48 +1000 Subject: [PATCH 10/50] Ensure handling of `getpwuid` giving `EINTR` is consistent --- src/coreclr/pal/src/thread/process.cpp | 3 ++- src/mono/mono/eventpipe/ds-rt-mono.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 2af7748f4dc694..68495c52618191 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -3490,7 +3490,8 @@ PROCGetProcessStatus( #ifdef __APPLE__ bool GetApplicationContainerFolder(PathCharString& buffer, const char *applicationGroupId, int applicationGroupIdLength) { - const char *homeDir = getpwuid(getuid())->pw_dir; + const char *homeDir; + while (nullptr == (homeDir = getpwuid(getuid())->pw_dir) && errno == EINTR); int homeDirLength = strlen(homeDir); // The application group container folder is defined as: diff --git a/src/mono/mono/eventpipe/ds-rt-mono.c b/src/mono/mono/eventpipe/ds-rt-mono.c index 58e8754f4290c5..4be589cbdfadf9 100644 --- a/src/mono/mono/eventpipe/ds-rt-mono.c +++ b/src/mono/mono/eventpipe/ds-rt-mono.c @@ -219,7 +219,8 @@ ds_rt_mono_transport_get_default_name ( // In sandbox, all IPC files (locks, pipes) should be written to the application group // container. The path returned by GetTempPathA will be unique for each process and cannot // be used for IPC between two different processes - const char *home_dir = getpwuid (getuid ())->pw_dir; + const char *home_dir; + while (NULL == (home_dir = getpwuid (getuid ())->pw_dir) && errno == EINTR); size_t home_dir_len = strlen (home_dir); // Verify the size of the path won't exceed maximum allowed size From 751656577af9cde60d5aae330426e150e8055276 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 10:36:38 +1000 Subject: [PATCH 11/50] Ensure handling of `recvmsg` giving `EINTR` is consistent --- src/native/libs/System.Native/pal_ifaddrs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/libs/System.Native/pal_ifaddrs.c b/src/native/libs/System.Native/pal_ifaddrs.c index b49edd513280e5..014b5b9d4521eb 100644 --- a/src/native/libs/System.Native/pal_ifaddrs.c +++ b/src/native/libs/System.Native/pal_ifaddrs.c @@ -638,7 +638,7 @@ static int parse_netlink_reply(struct netlink_session *session, struct ifaddrs * netlink_reply.msg_iovlen = 1; netlink_reply.msg_iov = &reply_vector; - length = recvmsg(session->sock_fd, &netlink_reply, 0); + while ((length = recvmsg(session->sock_fd, &netlink_reply, 0)) < 0 && errno == EINTR); LOG_DEBUG(" length == %d\n", (int)length); if (length < 0) { From 73d7e28ee919e584081cd5b6ccd309203dcf29d9 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 10:58:33 +1000 Subject: [PATCH 12/50] Ensure handling of `stat` giving `EINTR` is consistent - Excludes potential changes to external libs: brotli, libunwind, libtracepoint-control-cpp - Excludes potential changes to "templates" --- src/coreclr/hosts/corerun/corerun.hpp | 4 +++- .../nativeaot/Runtime/unix/PalCreateDump.cpp | 4 +++- src/coreclr/pal/src/file/directory.cpp | 8 ++++++-- src/coreclr/pal/src/file/file.cpp | 15 +++++++++++---- src/coreclr/pal/src/init/pal.cpp | 3 ++- src/coreclr/pal/src/loader/module.cpp | 4 +++- .../pal/src/sharedmemory/sharedmemory.cpp | 5 +++-- src/coreclr/pal/src/thread/process.cpp | 4 +++- src/coreclr/tools/superpmi/mcs/verbmerge.cpp | 3 ++- .../superpmi-shared/methodcontextreader.cpp | 4 +++- src/mono/mono/eglib/gfile-unix.c | 18 +++++++++++++++--- src/mono/mono/eglib/gpath.c | 4 +++- src/mono/wasi/runtime/driver.c | 4 +++- src/native/corehost/hostmisc/pal.unix.cpp | 4 +++- 14 files changed, 63 insertions(+), 21 deletions(-) diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 8c2d57fbb497b1..3c9caa58d6d021 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -441,7 +441,9 @@ namespace pal { // Check if the specified path exists struct stat sb; - if (stat(file_path, &sb) == -1) + int result; + while (-1 == (result = stat(file_path, &sb)) && errno == EINTR); + if (result == -1) { perror(W("Path not found")); return false; diff --git a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp index 48c977e4df7923..b24418984d061c 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp @@ -572,7 +572,9 @@ PalCreateDumpInitialize() strncat(program, DumpGeneratorName, programLen); struct stat fileData; - if (stat(program, &fileData) == -1 || !S_ISREG(fileData.st_mode)) + int stat_result; + while (-1 == (stat_result = stat(program, &fileData)) && errno == EINTR); + if (stat_result == -1 || !S_ISREG(fileData.st_mode)) { fprintf(stderr, "DOTNET_DbgEnableMiniDump is set and the createdump binary does not exist: %s\n", program); return true; diff --git a/src/coreclr/pal/src/file/directory.cpp b/src/coreclr/pal/src/file/directory.cpp index e06afd0b19e1c2..bf5604bb73fcad 100644 --- a/src/coreclr/pal/src/file/directory.cpp +++ b/src/coreclr/pal/src/file/directory.cpp @@ -144,7 +144,9 @@ RemoveDirectoryHelper ( { struct stat stat_data; - if ( stat( lpPathName, &stat_data) == 0 && + int stat_result; + while (-1 == (stat_result = stat( lpPathName, &stat_data)) && stat_result == EINTR); + if ( stat_result == 0 && (stat_data.st_mode & S_IFMT) == S_IFREG ) { /* Not a directory, it is a file. */ @@ -534,7 +536,9 @@ SetCurrentDirectoryA( { struct stat stat_data; - if ( stat( lpPathName, &stat_data) == 0 && + int stat_result; + while (-1 == (stat_result = stat( lpPathName, &stat_data)) && errno == EINTR); + if ( stat_result == 0 && (stat_data.st_mode & S_IFMT) == S_IFREG ) { /* Not a directory, it is a file. */ diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 1a134abab80af0..198c204adc8803 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -202,9 +202,14 @@ void FILEGetProperNotFoundError( LPCSTR lpPath, LPDWORD lpErrorCode ) /* If the last path component is a directory, we return file not found. If it's a file or doesn't exist, we return path not found. */ - if ( '\0' == *lpDupedPath || - ( stat( lpDupedPath, &stat_data ) == 0 && - ( stat_data.st_mode & S_IFMT ) == S_IFDIR ) ) + bool condition = '\0' == *lpDupedPath; + if (!condition) + { + int stat_result; + while (-1 == (stat_result = stat( lpDupedPath, &stat_data )) && errno == EINTR); + condition = stat_result == 0 && ( stat_data.st_mode & S_IFMT ) == S_IFDIR; + } + if (condition) { TRACE( "ERROR_FILE_NOT_FOUND\n" ); *lpErrorCode = ERROR_FILE_NOT_FOUND; @@ -524,7 +529,9 @@ CorUnix::InternalCreateFile( } else { struct stat st; - if (stat(lpUnixPath, &st) == 0 && (st.st_mode & S_IFDIR)) + int stat_result; + while (-1 == (stat_result = stat(lpUnixPath, &st)) && errno == EINTR); + if (stat_result == 0 && (st.st_mode & S_IFDIR)) { /* The file exists and it is a directory. Without FILE_FLAG_BACKUP_SEMANTICS, Win32 CreateFile always fails diff --git a/src/coreclr/pal/src/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index 6811690132daed..a4557b378b457a 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -1174,7 +1174,8 @@ static BOOL INIT_SharedFilesPath(void) // Check if the path already exists and it's a directory struct stat statInfo; - int statResult = stat(*gSharedFilesPath, &statInfo); + int statResult; + while (-1 == (statResult = stat(*gSharedFilesPath, &statInfo)) && errno == EINTR); // If the path exists, check that it's a directory if (statResult != 0 || !(statInfo.st_mode & S_IFDIR)) diff --git a/src/coreclr/pal/src/loader/module.cpp b/src/coreclr/pal/src/loader/module.cpp index d7cff970a0b02e..f66616c4be84e9 100644 --- a/src/coreclr/pal/src/loader/module.cpp +++ b/src/coreclr/pal/src/loader/module.cpp @@ -1072,7 +1072,9 @@ BOOL LOADSetExeName(LPWSTR name) ERROR("WCToMB failure, unable to get full name of exe\n"); goto exit; } - if (-1 == stat(pszExeName, &stat_buf)) + int stat_result; + while (-1 == (stat_result = stat(pszExeName, &stat_buf)) && errno == EINTR); + if (-1 == stat_result) { SetLastError(ERROR_MOD_NOT_FOUND); goto exit; diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 381a364e178358..fff98252cf33ca 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -178,7 +178,8 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( // Check if the path already exists struct stat statInfo; - int statResult = stat(path, &statInfo); + int statResult; + while (-1 == (statResult = stat(path, &statInfo)) && errno == -1); if (statResult != 0 && errno == ENOENT) { if (!createIfNotExist) @@ -276,7 +277,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( // Another process may have beaten us to it. Delete the temp directory and continue to check the requested directory to // see if it meets our needs. rmdir(tempPath); - statResult = stat(path, &statInfo); + while (-1 == (statResult = stat(path, &statInfo)) && errno == EINTR); } // If the path exists, check that it's a directory diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 68495c52618191..28b3daaaf3a359 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -3710,7 +3710,9 @@ checkFileType( LPCSTR lpFileName) } /* if it's not a PE/COFF file, check if it is executable */ - if ( -1 != stat( lpFileName, &stat_data ) ) + int stat_result; + while (-1 == (stat_result = stat( lpFileName, &stat_data )) && errno == EINTR); + if ( -1 != stat_result ) { if((stat_data.st_mode & S_IFMT) == S_IFDIR ) { diff --git a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp index 82a405072d69c8..2f3aa9b65948b3 100644 --- a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp +++ b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp @@ -474,7 +474,8 @@ int verbMerge::AppendAllInDir(HANDLE hFileOut, #else // TARGET_WINDOWS struct stat fileStat; char *fileFullPathUtf8 = ConvertWideCharToMultiByte(fileFullPath); - int st = stat(fileFullPathUtf8, &fileStat); + int st; + while (-1 == (st = stat(fileFullPathUtf8, &fileStat)) && errno == EINTR); if (st != 0) { LogError("Failed to stat file '%s'. errno=%d", fileFullPathUtf8, errno); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp index 529d8260b675c2..9c8a031041d096 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp @@ -43,7 +43,9 @@ bool test_filename_available(const std::string& path) return (attribs != INVALID_FILE_ATTRIBUTES) && !(attribs & FILE_ATTRIBUTE_DIRECTORY); #else // TARGET_WINDOWS struct stat stat_data; - if (stat(path.c_str(), &stat_data) != 0) + int stat_result; + while (-1 == (stat_result = stat(path.c_str(), &stat_data)) && errno == EINTR); + if (stat_result != 0) return false; return (stat_data.st_mode & S_IFMT) == S_IFREG; diff --git a/src/mono/mono/eglib/gfile-unix.c b/src/mono/mono/eglib/gfile-unix.c index 78815dc9c82bdd..2825ed8141caf4 100644 --- a/src/mono/mono/eglib/gfile-unix.c +++ b/src/mono/mono/eglib/gfile-unix.c @@ -67,7 +67,11 @@ g_file_test (const gchar *filename, GFileTest test) * such, workaround it. */ if (!have_stat) - have_stat = (stat (filename, &st) == 0); + { + int stat_result; + while (-1 == (stat_result = stat (filename, &st)) && errno == EINTR); + have_stat = (stat_result == 0); + } /* Hairy parens, but just manually try all permission bits */ if (have_stat && ( ((st.st_mode & S_IXOTH) @@ -86,13 +90,21 @@ g_file_test (const gchar *filename, GFileTest test) if ((test & G_FILE_TEST_IS_REGULAR) != 0) { if (!have_stat) - have_stat = (stat (filename, &st) == 0); + { + int stat_result; + while (-1 == (stat_result = stat (filename, &st)) && errno == EINTR); + have_stat = (stat_result == 0); + } if (have_stat && S_ISREG (st.st_mode)) return TRUE; } if ((test & G_FILE_TEST_IS_DIR) != 0) { if (!have_stat) - have_stat = (stat (filename, &st) == 0); + { + int stat_result; + while (-1 == (stat_result = stat (filename, &st)) && errno == EINTR); + have_stat = (stat_result == 0); + } if (have_stat && S_ISDIR (st.st_mode)) return TRUE; } diff --git a/src/mono/mono/eglib/gpath.c b/src/mono/mono/eglib/gpath.c index 96e39c3588dddd..78ed85081d9212 100644 --- a/src/mono/mono/eglib/gpath.c +++ b/src/mono/mono/eglib/gpath.c @@ -276,7 +276,9 @@ g_ensure_directory_exists (const gchar *filename) return FALSE; } - if (stat (dir, &sbuf) == 0 && S_ISDIR (sbuf.st_mode)) { + int stat_result; + while (-1 == (stat_result = stat (dir, &sbuf)) && errno == EINTR); + if (stat_result == 0 && S_ISDIR (sbuf.st_mode)) { g_free (dir); return TRUE; } diff --git a/src/mono/wasi/runtime/driver.c b/src/mono/wasi/runtime/driver.c index 6278f5bb8d2478..6e01667f069e0d 100644 --- a/src/mono/wasi/runtime/driver.c +++ b/src/mono/wasi/runtime/driver.c @@ -230,7 +230,9 @@ load_runtimeconfig (void) assert (num_char > 0 && num_char == str_len); - if (stat (file_path, &buffer) == 0) { + int stat_result; + while (-1 == (stat_result = stat (file_path, &buffer)) && errno == EINTR); + if (stat_result == 0) { MonovmRuntimeConfigArguments *arg = (MonovmRuntimeConfigArguments *)malloc (sizeof (MonovmRuntimeConfigArguments)); arg->kind = 0; arg->runtimeconfig.name.path = file_path; diff --git a/src/native/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp index 5bbb6aa5471bcc..f59476de4412bf 100644 --- a/src/native/corehost/hostmisc/pal.unix.cpp +++ b/src/native/corehost/hostmisc/pal.unix.cpp @@ -993,7 +993,9 @@ bool pal::file_exists(const pal::string_t& path) bool pal::is_directory(const pal::string_t& path) { struct stat sb; - if (::stat(path.c_str(), &sb) != 0) + int result; + while (-1 == (result = ::stat(path.c_str(), &sb)) && errno == EINTR); + if (result != 0) return false; return S_ISDIR(sb.st_mode); From 7e013bfab6280e39fe0cb2e2fb167915f94a5cb5 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 11:15:54 +1000 Subject: [PATCH 13/50] Ensure handling of variants of `stat` giving `EINTR` is consistent - Excludes potential changes to external lib libunwind - Excludes potential changes to "templates" --- src/coreclr/hosts/corerun/corerun.hpp | 4 +++- src/coreclr/pal/src/file/file.cpp | 6 ++++-- src/coreclr/pal/src/map/map.cpp | 10 +++++++--- src/coreclr/pal/src/sharedmemory/sharedmemory.cpp | 3 ++- src/mono/mono/eglib/gfile-posix.c | 4 +++- src/mono/mono/eglib/gfile-unix.c | 4 +++- src/mono/mono/utils/mono-filemap.c | 5 ++++- src/native/corehost/hostmisc/pal.unix.cpp | 4 +++- src/native/libs/System.Native/pal_io.c | 3 ++- 9 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 3c9caa58d6d021..3cda5c257e0c13 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -472,7 +472,9 @@ namespace pal return false; struct stat buf; - if (fstat(fd, &buf) == -1) + int fstat_result; + while (-1 == (fstat_result = fstat(fd, &buf)) && errno == EINTR); + if (fstat_result == -1) { close(fd); return false; diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 198c204adc8803..e64a355141f1d2 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -1506,7 +1506,7 @@ InternalSetFilePointerForUnixFd( struct stat fileData; int result; - result = fstat(iUnixFd, &fileData); + while (-1 == (result = fstat(iUnixFd, &fileData)) && errno == EINTR); if (result == -1) { // It's a bad fd. This shouldn't happen because @@ -1785,7 +1785,9 @@ CorUnix::InternalGetFileSize( goto InternalGetFileSizeExit; } - if (fstat(pLocalData->unix_fd, &stat_data) != 0) + int fstat_result; + while (-1 == (fstat_result = fstat(pLocalData->unix_fd, &stat_data)) && errno == EINTR); + if (fstat_result != 0) { ERROR("fstat failed of file descriptor %d\n", pLocalData->unix_fd); palError = FILEGetLastErrorFromErrno(); diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 8e8ee22046dc9c..06089a2d15712c 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -519,7 +519,9 @@ CorUnix::InternalCreateFileMapping( #endif // !CORECLR } - if (-1 == fstat(UnixFd, &UnixFileInformation)) + int fstat_result; + while (-1 == (fstat_result = fstat(UnixFd, &UnixFileInformation)) && errno == EINTR); + if (-1 == fstat_result) { ASSERT("fstat() failed for this reason %s.\n", strerror(errno)); palError = ERROR_INTERNAL_ERROR; @@ -598,7 +600,9 @@ CorUnix::InternalCreateFileMapping( { struct stat st; - if (0 == fstat(UnixFd, &st)) + int fstat_result; + while (-1 == (fstat_result = fstat(UnixFd, &st)) && errno == EINTR); + if (0 == fstat_result) { pLocalData->MappedFileDevNum = st.st_dev; pLocalData->MappedFileInodeNum = st.st_ino; @@ -1490,7 +1494,7 @@ static PAL_ERROR MAPGrowLocalFile( INT UnixFD, off_t NewSize ) non-standard. So I will try to enlarge a file, and if that fails try the less efficient way.*/ while (-1 == (TruncateRetVal = ftruncate( UnixFD, NewSize )) && errno == EINTR); - fstat( UnixFD, &FileInfo ); + while (-1 == fstat( UnixFD, &FileInfo ) && errno == EINTR); if ( TruncateRetVal != 0 || FileInfo.st_size != NewSize ) { diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index fff98252cf33ca..992bfdcf53b9e0 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -482,7 +482,8 @@ int SharedMemoryHelpers::CreateOrOpenFile( if (id->IsUserScope()) { struct stat statInfo; - int statResult = fstat(fileDescriptor, &statInfo); + int statResult; + while (-1 == (statResult = fstat(fileDescriptor, &statInfo)) && errno == EINTR); if (statResult != 0) { if (errors != nullptr) diff --git a/src/mono/mono/eglib/gfile-posix.c b/src/mono/mono/eglib/gfile-posix.c index f38db70c6a7b27..686e0f4b22a2a6 100644 --- a/src/mono/mono/eglib/gfile-posix.c +++ b/src/mono/mono/eglib/gfile-posix.c @@ -75,7 +75,9 @@ g_file_get_contents (const gchar *filename, gchar **contents, gsize *length, GEr return FALSE; } - if (fstat (fd, &st) != 0) { + int fstat_result; + while (-1 == (fstat_result = fstat (fd, &st)) && errno == EINTR); + if (fstat_result != 0) { if (gerror != NULL) { int err = errno; *gerror = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error in fstat()"); diff --git a/src/mono/mono/eglib/gfile-unix.c b/src/mono/mono/eglib/gfile-unix.c index 2825ed8141caf4..5eaddd52bfb67a 100644 --- a/src/mono/mono/eglib/gfile-unix.c +++ b/src/mono/mono/eglib/gfile-unix.c @@ -82,7 +82,9 @@ g_file_test (const gchar *filename, GFileTest test) } #ifdef HAVE_LSTAT if ((test & G_FILE_TEST_IS_SYMLINK) != 0) { - have_stat = (lstat (filename, &st) == 0); + int lstat_result; + while (-1 == (lstat_result = lstat (filename, &st)) && errno == EINTR); + have_stat = (lstat_result == 0); if (have_stat && S_ISLNK (st.st_mode)) return TRUE; } diff --git a/src/mono/mono/utils/mono-filemap.c b/src/mono/mono/utils/mono-filemap.c index 0c4ac46a5b4970..e4858d1be87ffd 100644 --- a/src/mono/mono/utils/mono-filemap.c +++ b/src/mono/mono/utils/mono-filemap.c @@ -10,6 +10,7 @@ */ #include "config.h" +#include #if HAVE_SYS_STAT_H #include @@ -48,7 +49,9 @@ guint64 mono_file_map_size (MonoFileMap *fmap) { struct stat stat_buf; - if (fstat (mono_file_map_fd (fmap), &stat_buf) < 0) + int result; + while (-1 == (result = fstat (mono_file_map_fd (fmap), &stat_buf)) && errno == EINTR); + if (result < 0) return 0; return stat_buf.st_size; } diff --git a/src/native/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp index f59476de4412bf..930cf1cc21cf0f 100644 --- a/src/native/corehost/hostmisc/pal.unix.cpp +++ b/src/native/corehost/hostmisc/pal.unix.cpp @@ -81,7 +81,9 @@ static void* map_file(const pal::string_t& path, size_t* length, int prot, int f } struct stat buf; - if (fstat(fd, &buf) != 0) + int fstat_result; + while (-1 == (fstat_result = fstat(fd, &buf)) && errno == EINTR); + if (fstat_result != 0) { trace::error(_X("Failed to map file. fstat(%s) failed with error %d"), path.c_str(), errno); close(fd); diff --git a/src/native/libs/System.Native/pal_io.c b/src/native/libs/System.Native/pal_io.c index 1b38ba4ce5711e..a5d667fb7b374b 100644 --- a/src/native/libs/System.Native/pal_io.c +++ b/src/native/libs/System.Native/pal_io.c @@ -262,7 +262,8 @@ int32_t SystemNative_FStat(intptr_t fd, FileStatus* output) int32_t SystemNative_LStat(const char* path, FileStatus* output) { struct stat_ result; - int ret = lstat_(path, &result); + int ret; + while (-1 == (ret = lstat_(path, &result)) && errno == EINTR); if (ret == 0) { From 085fd176658e14c22e7e482e98c71c79dbdc287d Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 11:27:42 +1000 Subject: [PATCH 14/50] Ensure handling of `unlink` giving `EINTR` is consistent - Excludes potential changes to external libs: brotli, libtracepoint-control-cpp --- src/coreclr/debug/debug-pal/unix/twowaypipe.cpp | 14 +++++++------- src/coreclr/pal/src/file/file.cpp | 6 ++++-- src/coreclr/pal/src/map/map.cpp | 4 ++-- src/coreclr/pal/src/sharedmemory/sharedmemory.cpp | 6 +++--- src/coreclr/pal/src/synchmgr/synchmanager.cpp | 10 +++++++--- src/coreclr/pal/src/synchobj/mutex.cpp | 4 ++-- src/mono/mono/eglib/gfile.c | 4 +++- src/mono/mono/eglib/test/file.c | 6 +++--- src/mono/mono/eventpipe/test/ep-teardown-tests.c | 4 ++-- src/mono/mono/mini/helpers.c | 4 ++-- src/mono/mono/mini/mini-posix.c | 2 +- src/mono/mono/mini/mini-runtime.c | 4 ++-- src/mono/mono/sgen/sgen-protocol.c | 2 +- src/native/eventpipe/ds-ipc-pal-socket.c | 4 ++-- .../System.Security.Cryptography.Native/pal_x509.c | 4 ++-- 15 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp index c94efcd18397e2..de2d45bb5a224f 100644 --- a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp +++ b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp @@ -22,7 +22,7 @@ bool TwoWayPipe::CreateServer(const ProcessDescriptor& pd) PAL_GetTransportPipeName(m_inPipeName, pd.m_Pid, pd.m_ApplicationGroupId, "in"); PAL_GetTransportPipeName(m_outPipeName, pd.m_Pid, pd.m_ApplicationGroupId, "out"); - unlink(m_inPipeName); + while (-1 == unlink(m_inPipeName) && errno == EINTR); if (mkfifo(m_inPipeName, S_IRWXU) == -1) { @@ -30,11 +30,11 @@ bool TwoWayPipe::CreateServer(const ProcessDescriptor& pd) } - unlink(m_outPipeName); + while (-1 == unlink(m_outPipeName) && errno == EINTR); if (mkfifo(m_outPipeName, S_IRWXU) == -1) { - unlink(m_inPipeName); + while (-1 == unlink(m_inPipeName) && errno == EINTR); return false; } @@ -166,8 +166,8 @@ bool TwoWayPipe::Disconnect() if (m_state == ServerConnected || m_state == Created) { - unlink(m_inPipeName); - unlink(m_outPipeName); + while (-1 == unlink(m_inPipeName) && errno == EINTR); + while (-1 == unlink(m_outPipeName) && errno == EINTR); } m_state = NotInitialized; @@ -178,6 +178,6 @@ bool TwoWayPipe::Disconnect() // and semaphores when the debugger detects the debuggee process exited. void TwoWayPipe::CleanupTargetProcess() { - unlink(m_inPipeName); - unlink(m_outPipeName); + while (-1 == unlink(m_inPipeName) && errno == EINTR); + while (-1 == unlink(m_outPipeName) && errno == EINTR); } diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index e64a355141f1d2..83bc8277433545 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -728,7 +728,9 @@ CorUnix::InternalCreateFile( } if (bFileCreated) { - if (-1 == unlink(lpUnixPath)) + int ulink_result; + while (-1 == (unlink_result = unlink(lpUnixPath)) && errno == EINTR); + if (-1 == unlink_result) { WARN("can't delete file; unlink() failed with errno %d (%s)\n", errno, strerror(errno)); @@ -957,7 +959,7 @@ DeleteFileA( } } - result = unlink( lpFullunixFileName ); + while (-1 == (result = unlink( lpFullunixFileName )) && errno == EINTR); if (result < 0) { diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 06089a2d15712c..963f8dcf3310b7 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -195,7 +195,7 @@ FileMappingCleanupRoutine( if (pImmutableData->bPALCreatedTempFile) { - unlink(pImmutableData->lpFileName); + while (-1 == unlink(pImmutableData->lpFileName) && errno == EINTR); } if (FALSE == fShutdown) @@ -655,7 +655,7 @@ CorUnix::InternalCreateFileMapping( if (bPALCreatedTempFile) { - unlink(pImmutableData->lpFileName); + while (-1 == unlink(pImmutableData->lpFileName) && errno == EINTR); } if (-1 != UnixFd) diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 992bfdcf53b9e0..95d94d2b323508 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -570,7 +570,7 @@ int SharedMemoryHelpers::CreateOrOpenFile( } CloseFile(fileDescriptor); - unlink(path); + while (-1 == unlink(path) && errno == EINTR); throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } @@ -1037,7 +1037,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( if (m_createdFile) { _ASSERTE(m_filePath != nullptr); - unlink(*m_filePath); + while (-1 == unlink(m_filePath) && errno == EINTR); } if (m_sessionDirectoryPathCharCount != 0) @@ -1395,7 +1395,7 @@ void SharedMemoryProcessDataHeader::Close() path.Append('/')); SIZE_T sessionDirectoryPathCharCount = path.GetCount(); SharedMemoryHelpers::VerifyStringOperation(path.Append(m_id.GetName(), m_id.GetNameCharCount())); - unlink(path); + while (-1 == unlink(path) && errno == EINTR); path.CloseBuffer(sessionDirectoryPathCharCount); rmdir(path); } diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index 51b3ddff78ee32..7c14b38802b3ca 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -2724,7 +2724,9 @@ namespace CorUnix { /* Some how no one deleted the pipe, perhaps it was left behind from a crash?? Delete the pipe and try again. */ - if (-1 == unlink(szPipeFilename)) + int unlink_result; + while (-1 == (unlink_result = unlink(szPipeFilename)) && errno == EINTR); + if (-1 == unlink_result) { ERROR( "Unable to delete the process pipe that was left behind.\n" ); fRet = false; @@ -2814,7 +2816,7 @@ namespace CorUnix // Failed if (0 != szPipeFilename[0]) { - unlink(szPipeFilename); + while (-1 == unlink(szPipeFilename) && errno == EINTR); } if (-1 != iPipeRd) { @@ -2862,7 +2864,9 @@ namespace CorUnix if (GetProcessPipeName(szPipeFilename, MAX_PATH, gPID)) { - if (unlink(szPipeFilename) == -1) + int unlink_result; + while (-1 == (unlink_result = unlink(szPipeFilename)) && errno == EINTR); + if (unlink_result == -1) { ERROR("Unable to unlink the pipe file name errno=%d (%s)\n", errno, strerror(errno)); diff --git a/src/coreclr/pal/src/synchobj/mutex.cpp b/src/coreclr/pal/src/synchobj/mutex.cpp index f23254612c555c..b8690e9b4fb98f 100644 --- a/src/coreclr/pal/src/synchobj/mutex.cpp +++ b/src/coreclr/pal/src/synchobj/mutex.cpp @@ -1154,7 +1154,7 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( if (m_createdLockFile) { _ASSERTE(m_lockFilePath != nullptr); - unlink(*m_lockFilePath); + while (-1 == unlink(*m_lockFilePath) && errno == EINTR); } if (m_sessionDirectoryPathCharCount != 0) @@ -1423,7 +1423,7 @@ void NamedMutexProcessData::Close(bool isAbruptShutdown, bool releaseSharedData) path.Append('/')); SIZE_T sessionDirectoryPathCharCount = path.GetCount(); SharedMemoryHelpers::VerifyStringOperation(path.Append(id->GetName(), id->GetNameCharCount())); - unlink(path); + while (-1 == unlink(path) && errno == EINTR); path.CloseBuffer(sessionDirectoryPathCharCount); rmdir(path); } diff --git a/src/mono/mono/eglib/gfile.c b/src/mono/mono/eglib/gfile.c index 5720a54a712658..3dbf322b6809cd 100644 --- a/src/mono/mono/eglib/gfile.c +++ b/src/mono/mono/eglib/gfile.c @@ -189,6 +189,8 @@ g_unlink (const gchar *path) return ret; } #else - return unlink (path); + int result; + while (-1 == (result = unlink (path)) && errno == EINTR); + return result; #endif } diff --git a/src/mono/mono/eglib/test/file.c b/src/mono/mono/eglib/test/file.c index 25473c03c857a3..ee30c77750f723 100644 --- a/src/mono/mono/eglib/test/file.c +++ b/src/mono/mono/eglib/test/file.c @@ -104,7 +104,7 @@ test_open_tmp (void) if (name == NULL) return FAILED ("No name returned."); close (fd); - unlink (name); + while (-1 == unlink (name) && errno == EINTR); g_free (name); return OK; } @@ -195,7 +195,7 @@ test_file (void) if (!res) return FAILED ("4 %s should be a symlink", sympath); - unlink (path); + while (-1 == unlink (path) && errno == EINTR); res = g_file_test (sympath, G_FILE_TEST_EXISTS); if (res) @@ -212,7 +212,7 @@ test_file (void) res = g_file_test (sympath, G_FILE_TEST_IS_SYMLINK); if (!res) return FAILED ("5 %s should be a symlink", sympath); - unlink (sympath); + while (-1 == unlink (sympath) && errno == EINTR); g_free (sympath); #endif g_free (path); diff --git a/src/mono/mono/eventpipe/test/ep-teardown-tests.c b/src/mono/mono/eventpipe/test/ep-teardown-tests.c index 3f1d75572ce6ed..4608af3997078f 100644 --- a/src/mono/mono/eventpipe/test/ep-teardown-tests.c +++ b/src/mono/mono/eventpipe/test/ep-teardown-tests.c @@ -13,8 +13,8 @@ test_teardown (void) if (eventpipe_test_domain) mono_jit_cleanup (eventpipe_test_domain); - unlink (TEST_FILE_2); - unlink (TEST_FILE); + while (-1 == unlink (TEST_FILE_2) && errno == EINTR); + while (-1 == unlink (TEST_FILE) && errno == EINTR); return NULL; } diff --git a/src/mono/mono/mini/helpers.c b/src/mono/mono/mini/helpers.c index e3860045d244c4..3bcc589f7892cd 100644 --- a/src/mono/mono/mini/helpers.c +++ b/src/mono/mono/mini/helpers.c @@ -280,8 +280,8 @@ MONO_RESTORE_WARNING #endif /* HAVE_SYSTEM */ #ifndef HOST_WIN32 - unlink (o_file); - unlink (as_file); + while (-1 == unlink (o_file) && errno == EINTR); + while (-1 == unlink (as_file) && errno == EINTR); #endif g_free (o_file); g_free (as_file); diff --git a/src/mono/mono/mini/mini-posix.c b/src/mono/mono/mini/mini-posix.c index f67fbeaed83c0f..5a13d797dd88ae 100644 --- a/src/mono/mono/mini/mini-posix.c +++ b/src/mono/mono/mini/mini-posix.c @@ -1006,7 +1006,7 @@ mono_gdb_render_native_backtraces (pid_t crashed_pid) g_async_safe_printf ("mono_gdb_render_native_backtraces not supported on this platform, unable to find gdb or lldb\n"); close (commands_handle); - unlink (commands_filename); + while (-1 == unlink (commands_filename) && errno == EINTR); return; exec: diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 55645dd51efb46..b54a8e510ecdb8 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -1986,7 +1986,7 @@ mono_enable_jit_map (void) if (!perf_map_file) { char name [64]; g_snprintf (name, sizeof (name), "/tmp/perf-%d.map", getpid ()); - unlink (name); + while (-1 == unlink (name) && errno == EINTR); perf_map_file = fopen (name, "w"); } } @@ -2111,7 +2111,7 @@ mono_enable_jit_dump (void) mono_os_mutex_lock (&perf_dump_mutex); g_snprintf (name, sizeof (name), "/tmp/jit-%d.dump", perf_dump_pid); - unlink (name); + while (-1 == unlink (name) && errno == EINTR); perf_dump_file = fopen (name, "w+"); add_file_header_info (&header); diff --git a/src/mono/mono/sgen/sgen-protocol.c b/src/mono/mono/sgen/sgen-protocol.c index aea3acca131c4c..4e508a6d38b932 100644 --- a/src/mono/mono/sgen/sgen-protocol.c +++ b/src/mono/mono/sgen/sgen-protocol.c @@ -263,7 +263,7 @@ binary_protocol_check_file_overflow (void) if (current_file_index > 0) { char *filename = filename_for_index (current_file_index - 1); - unlink (filename); + while (-1 == unlink (filename) && errno == EINTR); free_filename (filename); } diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index a05084851fe33c..f39a7c98dfcddd 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -1209,7 +1209,7 @@ ds_ipc_listen ( #ifdef DS_IPC_PAL_AF_UNIX int result_unlink; DS_ENTER_BLOCKING_PAL_SECTION; - result_unlink = unlink (((struct sockaddr_un *)ipc->server_address)->sun_path); + while (-1 == (result_unlink = unlink (((struct sockaddr_un *)ipc->server_address)->sun_path)) && errno == EINTR); DS_EXIT_BLOCKING_PAL_SECTION; EP_ASSERT (result_unlink != -1); @@ -1351,7 +1351,7 @@ ds_ipc_close ( // reference to it is closed." - unix(7) man page int result_unlink; DS_ENTER_BLOCKING_PAL_SECTION; - result_unlink = unlink (((struct sockaddr_un *)ipc->server_address)->sun_path); + while (-1 == (result_unlink = unlink (((struct sockaddr_un *)ipc->server_address)->sun_path)) && errno == EINTR); DS_EXIT_BLOCKING_PAL_SECTION; if (result_unlink == -1) { diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c index 53b2af5f033e3d..73ddebb4f7d596 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c @@ -1158,7 +1158,7 @@ int32_t CryptoNative_X509ChainGetCachedOcspStatus(X509_STORE_CTX* storeCtx, char // may have been reported while determining we want to delete it and ask again fresh. if (ret == PAL_X509_V_ERR_UNABLE_TO_GET_CRL) { - unlink(fullPath); + while (-1 == unlink(fullPath) && errno == EINTR); ERR_clear_error(); } @@ -1272,7 +1272,7 @@ static int32_t X509ChainVerifyOcsp(X509_STORE_CTX* storeCtx, X509* subject, X509 if (clearErr) { ERR_clear_error(); - unlink(fullPath); + while (-1 == unlink(fullPath) && errno == EINTR); } free(fullPath); From 9776101d2de19a594fd67e06689822bf5d5ad76d Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 11:29:19 +1000 Subject: [PATCH 15/50] Ensure handling of `shm_unlink` giving `EINTR` is consistent --- src/coreclr/minipal/Unix/doublemapping.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/minipal/Unix/doublemapping.cpp b/src/coreclr/minipal/Unix/doublemapping.cpp index 2380e5ae41d4a2..831af919352c6a 100644 --- a/src/coreclr/minipal/Unix/doublemapping.cpp +++ b/src/coreclr/minipal/Unix/doublemapping.cpp @@ -70,9 +70,9 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu char name[24]; sprintf(name, "/shm-dotnet-%d", getpid()); name[sizeof(name) - 1] = '\0'; - shm_unlink(name); + while (-1 == shm_unlink(name) && errno == EINTR); fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); - shm_unlink(name); + while (-1 == shm_unlink(name) && errno == EINTR); } #endif // !TARGET_ANDROID @@ -383,9 +383,9 @@ TemplateThunkMappingData *InitializeTemplateThunkMappingData(void* pTemplate) char name[24]; sprintf(name, "/shm-dotnet-template-%d", getpid()); name[sizeof(name) - 1] = '\0'; - shm_unlink(name); + while (-1 == shm_unlink(name) && errno == EINTR); fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); - shm_unlink(name); + while (-1 == shm_unlink(name) && errno == EINTR); } #endif // !TARGET_ANDROID #endif From 651d928ec382cb8854b7b8e5c12c9037b3067e61 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 11:36:58 +1000 Subject: [PATCH 16/50] Ensure handling of `pipe{2}` giving `EINTR` is consistent - Excludes potential changes to external lib libunwind --- src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp | 4 +++- src/coreclr/pal/src/file/file.cpp | 4 +++- src/coreclr/pal/src/synchmgr/synchmanager.cpp | 8 +++++--- src/coreclr/pal/src/thread/process.cpp | 8 ++++++-- src/coreclr/pal/src/thread/threadsusp.cpp | 4 +++- src/mono/mono/profiler/log.c | 4 +++- src/native/libs/System.Native/pal_process.c | 2 +- 7 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp index b24418984d061c..582774a94621c0 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp @@ -214,7 +214,9 @@ CreateCrashDump( int cbErrorMessageBuffer) { int pipe_descs[2]; - if (pipe(pipe_descs) == -1) + int pipe_result; + while (-1 == (pipe_result = pipe(pipe_descs)) && errno == EINTR); + if (pipe_result == -1) { if (errorMessageBuffer != nullptr) { diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 83bc8277433545..88f1d7f6247d8d 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -2172,7 +2172,9 @@ CorUnix::InternalCreatePipe( goto InternalCreatePipeExit; } - if (pipe(readWritePipeDes) == -1) + int pipe_result; + while (-1 == (pipe_result = pipe(readWritePipeDes)) && errno == EINTR); + if (pipe_result == -1) { ERROR("pipe() call failed errno:%d (%s) \n", errno, strerror(errno)); palError = ERROR_INTERNAL_ERROR; diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index 7c14b38802b3ca..0e5d2bb716797f 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -2767,12 +2767,14 @@ namespace CorUnix } #else // !CORECLR int rgiPipe[] = { -1, -1 }; - int pipeRv = + int pipeRv; + while (-1 == (pipeRv = #if HAVE_PIPE2 - pipe2(rgiPipe, O_CLOEXEC); + pipe2(rgiPipe, O_CLOEXEC) #else - pipe(rgiPipe); + pipe(rgiPipe) #endif // HAVE_PIPE2 + ) && errno == EINTR); if (pipeRv == -1) { ERROR("Unable to create the process pipe\n"); diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 28b3daaaf3a359..ffaaae2a8823a8 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -773,7 +773,9 @@ CorUnix::InternalCreateProcess( { int pipe_descs[2]; - if (-1 == pipe(pipe_descs)) + int pipe_result; + while (-1 == (pipe_result = pipe(pipe_descs)) && errno == EINTR); + if (-1 == pipe_result) { ERROR("pipe() failed! error is %d (%s)\n", errno, strerror(errno)); palError = ERROR_NOT_ENOUGH_MEMORY; @@ -2216,7 +2218,9 @@ PROCCreateCrashDump( } int pipe_descs[2]; - if (pipe(pipe_descs) == -1) + int pipe_result; + while (-1 == (pipe_result = pipe(pipe_descs)) && errno == EINTR); + if (pipe_result == -1) { if (errorMessageBuffer != nullptr) { diff --git a/src/coreclr/pal/src/thread/threadsusp.cpp b/src/coreclr/pal/src/thread/threadsusp.cpp index ec6cea6c2c1d86..1848c9257cb72b 100644 --- a/src/coreclr/pal/src/thread/threadsusp.cpp +++ b/src/coreclr/pal/src/thread/threadsusp.cpp @@ -74,12 +74,14 @@ CThreadSuspensionInfo::InternalSuspendNewThreadFromData( ReleaseSuspensionLock(pThread); int pipe_descs[2]; - int pipeRv = + int pipeRv; + while (-1 == (pipeRv = #if HAVE_PIPE2 pipe2(pipe_descs, O_CLOEXEC); #else pipe(pipe_descs); #endif // HAVE_PIPE2 + ) && errno == EINTR); if (pipeRv == -1) { ERROR("pipe() failed! error is %d (%s)\n", errno, strerror(errno)); diff --git a/src/mono/mono/profiler/log.c b/src/mono/mono/profiler/log.c index 24d3834296604f..18803e7be67306 100644 --- a/src/mono/mono/profiler/log.c +++ b/src/mono/mono/profiler/log.c @@ -2897,7 +2897,9 @@ static void start_helper_thread (void) { #ifdef HAVE_COMMAND_PIPES - if (pipe (log_profiler.pipes) == -1) { + int pipe_result; + while (-1 == (pipe_result = pipe (log_profiler.pipes)) && errno == EINTR); + if (pipe_result == -1) { mono_profiler_printf_err ("Could not create log profiler pipe: %s", g_strerror (errno)); exit (1); } diff --git a/src/native/libs/System.Native/pal_process.c b/src/native/libs/System.Native/pal_process.c index 1e01eb22c238c4..007945af5f3130 100644 --- a/src/native/libs/System.Native/pal_process.c +++ b/src/native/libs/System.Native/pal_process.c @@ -304,7 +304,7 @@ int32_t SystemNative_ForkAndExecProcess(const char* filename, // Process is still the clone of this one. This is a best-effort attempt, so ignore any errors. // If the child fails to exec we use the pipe to pass the errno to the parent process. #if HAVE_PIPE2 - (void)! pipe2(waitForChildToExecPipe, O_CLOEXEC); + while (-1 == pipe2(waitForChildToExecPipe, O_CLOEXEC) && errno == EINTR); #else (void)! SystemNative_Pipe(waitForChildToExecPipe, PAL_O_CLOEXEC); #endif From f4cb957a0afc4678eee0009b84890d4432204ba1 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 11:45:25 +1000 Subject: [PATCH 17/50] Ensure handling of `mkdir` giving `EINTR` is consistent --- src/coreclr/pal/src/file/directory.cpp | 4 +++- src/coreclr/pal/src/sharedmemory/sharedmemory.cpp | 3 ++- src/mono/mono/eglib/gfile-unix.c | 8 ++++++-- src/mono/mono/eglib/gpath.c | 2 +- .../mono/tests/split-tailcall-interface-conservestack.cpp | 2 +- src/mono/mono/tests/tailcall/split-fsharp.cpp | 2 +- src/native/corehost/hostmisc/pal.h | 4 +++- src/native/corehost/hostmisc/pal.unix.cpp | 4 +++- 8 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/coreclr/pal/src/file/directory.cpp b/src/coreclr/pal/src/file/directory.cpp index bf5604bb73fcad..18265ec8f45d3f 100644 --- a/src/coreclr/pal/src/file/directory.cpp +++ b/src/coreclr/pal/src/file/directory.cpp @@ -457,7 +457,9 @@ CreateDirectoryA( // Canonicalize the path so we can determine its length. FILECanonicalizePath(realPathBuf); - if ( mkdir(realPathBuf, mode) != 0 ) + int mkdir_result; + while (-1 == (mkdir_result = mkdir(realPathBuf, mode)) && errno == EINTR); + if ( mkdir_result != 0 ) { TRACE("Creation of directory [%s] was unsuccessful, errno = %d.\n", unixPathName, errno); diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 95d94d2b323508..4e4d7f14130f19 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -196,7 +196,8 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( if (isGlobalLockAcquired) { - int operationResult = mkdir(path, permissionsMask); + int operationResult; + while (-1 == (mkdir_result = mkdir(path, permissionsMask)) && errno == EINTR); if (operationResult != 0) { if (errors != nullptr) diff --git a/src/mono/mono/eglib/gfile-unix.c b/src/mono/mono/eglib/gfile-unix.c index 5eaddd52bfb67a..8b92f0c0156652 100644 --- a/src/mono/mono/eglib/gfile-unix.c +++ b/src/mono/mono/eglib/gfile-unix.c @@ -131,8 +131,12 @@ g_mkdtemp (char *temp) #else temp = mktemp (g_strdup (temp)); /* 0700 is the mode specified in specs */ - if (temp && *temp && mkdir (temp, 0700) == 0) - return temp; + if (temp && *temp) + { + int mkdir_result; + while (-1 == (mkdir_result = mkdir (temp, 0700)) && errno == EINTR); + if (mkdir_result == 0) return temp; + } g_free (temp); return NULL; diff --git a/src/mono/mono/eglib/gpath.c b/src/mono/mono/eglib/gpath.c index 78ed85081d9212..3eab361543b711 100644 --- a/src/mono/mono/eglib/gpath.c +++ b/src/mono/mono/eglib/gpath.c @@ -291,7 +291,7 @@ g_ensure_directory_exists (const gchar *filename) p = strchr (p, '/'); if (p) *p = '\0'; - retval = mkdir (dir, 0777); + while (-1 == (retval = mkdir (dir, 0777)) && errno == EINTR); if (retval != 0 && errno != EEXIST) { g_free (dir); return FALSE; diff --git a/src/mono/mono/tests/split-tailcall-interface-conservestack.cpp b/src/mono/mono/tests/split-tailcall-interface-conservestack.cpp index 10e38b73c93af0..642210ac6cfeda 100644 --- a/src/mono/mono/tests/split-tailcall-interface-conservestack.cpp +++ b/src/mono/mono/tests/split-tailcall-interface-conservestack.cpp @@ -34,7 +34,7 @@ CreateDir (const char *a) #ifdef _WIN32 _mkdir (a); #else - mkdir (a, 0777); + while (-1 == mkdir (a, 0777) && errno == EINTR); #endif } diff --git a/src/mono/mono/tests/tailcall/split-fsharp.cpp b/src/mono/mono/tests/tailcall/split-fsharp.cpp index 35e09001411439..386a67ce576392 100644 --- a/src/mono/mono/tests/tailcall/split-fsharp.cpp +++ b/src/mono/mono/tests/tailcall/split-fsharp.cpp @@ -42,7 +42,7 @@ CreateDir (const char *a) #ifdef _WIN32 _mkdir (a); #else - mkdir (a, 0777); + while (-1 == mkdir (a, 0777) && errno == EINTR); #endif } diff --git a/src/native/corehost/hostmisc/pal.h b/src/native/corehost/hostmisc/pal.h index 484aedef68fba2..4465c6e5b1982c 100644 --- a/src/native/corehost/hostmisc/pal.h +++ b/src/native/corehost/hostmisc/pal.h @@ -248,7 +248,9 @@ namespace pal inline bool mkdir(const char_t* dir, int mode, int& error_code) { - int ret = ::mkdir(dir, mode); + int ret; + while (-1 == (ret = ::mkdir(dir, mode)) && errno == EINTR); + if (ret == 0) return true; diff --git a/src/native/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp index 930cf1cc21cf0f..4b08394baa286b 100644 --- a/src/native/corehost/hostmisc/pal.unix.cpp +++ b/src/native/corehost/hostmisc/pal.unix.cpp @@ -402,7 +402,9 @@ bool pal::get_default_bundle_extraction_base_dir(pal::string_t& extraction_dir) } // Create $HOME/.net with rwx access to the owner - if (::mkdir(extraction_dir.c_str(), S_IRWXU) == 0) + int mkdir_error; + while (-1 == (mkdir_error = ::mkdir(extraction_dir.c_str(), S_IRWXU)) && errno == EINTR); + if (mkdir_error == 0) { return true; } From 1465bf937f7ed86838db94b7791e79ea3f427c23 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 12:57:58 +1000 Subject: [PATCH 18/50] Ensure handling of `chdir` giving `EINTR` is consistent - Excludes potential changes to "templates" --- src/coreclr/pal/src/file/directory.cpp | 2 +- src/mono/mono/eglib/test/path.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/coreclr/pal/src/file/directory.cpp b/src/coreclr/pal/src/file/directory.cpp index 18265ec8f45d3f..93ad5e4d5fb2aa 100644 --- a/src/coreclr/pal/src/file/directory.cpp +++ b/src/coreclr/pal/src/file/directory.cpp @@ -526,7 +526,7 @@ SetCurrentDirectoryA( } TRACE("Attempting to open Unix dir [%s]\n", lpPathName); - result = chdir(lpPathName); + while (-1 == (result = chdir (lpPathName)) && errno == EINTR); if ( result == 0 ) { diff --git a/src/mono/mono/eglib/test/path.c b/src/mono/mono/eglib/test/path.c index f626a7666e0afb..d2a6fa3256be8e 100644 --- a/src/mono/mono/eglib/test/path.c +++ b/src/mono/mono/eglib/test/path.c @@ -267,7 +267,9 @@ test_cwd (void) return FAILED ("No current directory?"); g_free (dir); - if (chdir (newdir) == -1) + int chdir_result; + while (-1 == (chdir_result = chdir (newdir)) && errno == EINTR); + if (chdir_result == -1) return FAILED ("No %s?", newdir); dir = g_get_current_dir (); From f671ff18f7e6e3af4f423095e201aa3491f2dce9 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:03:31 +1000 Subject: [PATCH 19/50] Ensure handling of `mkfifo` giving `EINTR` is consistent --- src/coreclr/debug/debug-pal/unix/twowaypipe.cpp | 8 ++++++-- src/coreclr/pal/src/synchmgr/synchmanager.cpp | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp index de2d45bb5a224f..a140a559d332d0 100644 --- a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp +++ b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#include #include #include #include @@ -24,7 +25,9 @@ bool TwoWayPipe::CreateServer(const ProcessDescriptor& pd) while (-1 == unlink(m_inPipeName) && errno == EINTR); - if (mkfifo(m_inPipeName, S_IRWXU) == -1) + int mkfifo_result; + while (-1 == (mkfifo_result = mkfifo(m_inPipeName, S_IRWXU)) && errno == EINTR); + if (mkfifo_result == -1) { return false; } @@ -32,7 +35,8 @@ bool TwoWayPipe::CreateServer(const ProcessDescriptor& pd) while (-1 == unlink(m_outPipeName) && errno == EINTR); - if (mkfifo(m_outPipeName, S_IRWXU) == -1) + while (-1 == (mkfifo_result = mkfifo(m_outPipeName, S_IRWXU)) && errno == EINTR); + if (mkfifo_result == -1) { while (-1 == unlink(m_inPipeName) && errno == EINTR); return false; diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index 0e5d2bb716797f..88ebb82c7370df 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -2718,7 +2718,9 @@ namespace CorUnix } /* create the pipe, with full access to the owner only */ - if (mkfifo(szPipeFilename, S_IRWXU) == -1) + int mkfifo_result; + while (-1 == (mkfifo_result = mkfifo(szPipeFilename, S_IRWXU)) && errno == EINTR); + if (mkfifo_result == -1) { if (errno == EEXIST) { @@ -2734,7 +2736,8 @@ namespace CorUnix } else { - if (mkfifo(szPipeFilename, S_IRWXU) == -1) + while (-1 == (mkfifo_result = mkfifo(szPipeFilename, S_IRWXU)) && errno == EINTR); + if (mkfifo_result == -1) { ERROR( "Still unable to create the process pipe...giving up!\n" ); fRet = false; From e01584a455cb02c79731c8f4e06e23ca433b672d Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:10:57 +1000 Subject: [PATCH 20/50] Ensure handling of `rename` giving `EINTR` is consistent --- src/coreclr/pal/src/sharedmemory/sharedmemory.cpp | 5 ++++- src/mono/mono/eglib/gfile.c | 4 +++- src/native/corehost/hostmisc/pal.h | 9 ++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 4e4d7f14130f19..e1f73ca2bc6e6f 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "pal/dbgmsg.h" +#include SET_DEFAULT_DEBUG_CHANNEL(SHMEM); // some headers have code with asserts, so do this first #include "pal/sharedmemory.h" @@ -270,7 +271,9 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } - if (rename(tempPath, path) == 0) + int rename_result; + while (-1 == (rename_result = rename(tempPath, path)) && errno == EINTR); + if (rename_result == 0) { return true; } diff --git a/src/mono/mono/eglib/gfile.c b/src/mono/mono/eglib/gfile.c index 3dbf322b6809cd..947af0e6d257ff 100644 --- a/src/mono/mono/eglib/gfile.c +++ b/src/mono/mono/eglib/gfile.c @@ -167,7 +167,9 @@ g_rename (const gchar *src_path, const gchar *dst_path) return ret; } #else - return rename (src_path, dst_path); + int rename_result; + while (-1 == (rename_result = rename(src_path, dst_path)) && errno == EINTR); + return rename_result; #endif } diff --git a/src/native/corehost/hostmisc/pal.h b/src/native/corehost/hostmisc/pal.h index 4465c6e5b1982c..2fa0a22118f75f 100644 --- a/src/native/corehost/hostmisc/pal.h +++ b/src/native/corehost/hostmisc/pal.h @@ -259,7 +259,14 @@ namespace pal } inline bool rmdir(const char_t* path) { return ::rmdir(path) == 0; } - inline int rename(const char_t* old_name, const char_t* new_name) { return ::rename(old_name, new_name); } + + inline int rename(const char_t* old_name, const char_t* new_name) + { + int result; + while (-1 == (result = ::rename(old_name, new_name)) && errno == EINTR); + return result; + } + inline int remove(const char_t* path) { return ::remove(path); } inline bool munmap(void* addr, size_t length) { return ::munmap(addr, length) == 0; } inline int get_pid() { return getpid(); } From 33759b66bd5c8705a617480a13b5e0325268b912 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:13:30 +1000 Subject: [PATCH 21/50] Ensure handling of `rmdir` giving `EINTR` is consistent --- src/coreclr/pal/src/sharedmemory/sharedmemory.cpp | 10 +++++----- src/coreclr/pal/src/synchobj/mutex.cpp | 4 ++-- src/native/corehost/hostmisc/pal.h | 7 ++++++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index e1f73ca2bc6e6f..77c590b5c90119 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -229,7 +229,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( GetFriendlyErrorCodeString(errorCode)); } - rmdir(path); + while (-1 == rmdir(path) && errno == EINTR); throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } @@ -267,7 +267,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( GetFriendlyErrorCodeString(errorCode)); } - rmdir(tempPath); + while (-1 == rmdir(tempPath) && errno == EINTR); throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } @@ -280,7 +280,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( // Another process may have beaten us to it. Delete the temp directory and continue to check the requested directory to // see if it meets our needs. - rmdir(tempPath); + while (-1 == rmdir(tempPath) && errno == EINTR); while (-1 == (statResult = stat(path, &statInfo)) && errno == EINTR); } @@ -1048,7 +1048,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( { _ASSERTE(*m_filePath != nullptr); m_filePath->CloseBuffer(m_sessionDirectoryPathCharCount); - rmdir(*m_filePath); + while (-1 == rmdir(*m_filePath) && errno == EINTR); } if (m_acquiredCreationDeletionFileLockForId != nullptr) @@ -1401,7 +1401,7 @@ void SharedMemoryProcessDataHeader::Close() SharedMemoryHelpers::VerifyStringOperation(path.Append(m_id.GetName(), m_id.GetNameCharCount())); while (-1 == unlink(path) && errno == EINTR); path.CloseBuffer(sessionDirectoryPathCharCount); - rmdir(path); + while (-1 == rmdir(path) && errno == EINTR); } catch (SharedMemoryException) { diff --git a/src/coreclr/pal/src/synchobj/mutex.cpp b/src/coreclr/pal/src/synchobj/mutex.cpp index b8690e9b4fb98f..f69d34933fc1c3 100644 --- a/src/coreclr/pal/src/synchobj/mutex.cpp +++ b/src/coreclr/pal/src/synchobj/mutex.cpp @@ -1161,7 +1161,7 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( { _ASSERTE(m_lockFilePath != nullptr); m_lockFilePath->CloseBuffer(m_sessionDirectoryPathCharCount); - rmdir(*m_lockFilePath); + while (-1 == rmdir(*m_lockFilePath) && errno == EINTR); } } #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX @@ -1425,7 +1425,7 @@ void NamedMutexProcessData::Close(bool isAbruptShutdown, bool releaseSharedData) SharedMemoryHelpers::VerifyStringOperation(path.Append(id->GetName(), id->GetNameCharCount())); while (-1 == unlink(path) && errno == EINTR); path.CloseBuffer(sessionDirectoryPathCharCount); - rmdir(path); + while (-1 == rmdir(path) && errno == EINTR); } catch (SharedMemoryException) { diff --git a/src/native/corehost/hostmisc/pal.h b/src/native/corehost/hostmisc/pal.h index 2fa0a22118f75f..42ed0782493278 100644 --- a/src/native/corehost/hostmisc/pal.h +++ b/src/native/corehost/hostmisc/pal.h @@ -258,7 +258,12 @@ namespace pal return false; } - inline bool rmdir(const char_t* path) { return ::rmdir(path) == 0; } + inline bool rmdir(const char_t* path) + { + int result; + while (-1 == (result = ::rmdir(path)) && errno == EINTR); + return result == 0; + } inline int rename(const char_t* old_name, const char_t* new_name) { From ddec1a9a06a92d8345fe94e8ef427b2577e0544c Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:24:01 +1000 Subject: [PATCH 22/50] Ensure handling of `ioctl` giving `EINTR` is consistent - Excludes potential changes to libtracepoint-control-cpp --- src/native/eventpipe/ep-session-provider.c | 8 ++++++-- .../libs/System.IO.Ports.Native/pal_serial.c | 6 ++++-- .../libs/System.IO.Ports.Native/pal_termios.c | 20 ++++++++++++++----- .../System.IO.Ports.Native/pal_termios2.c | 8 ++++++-- src/native/libs/System.Native/pal_console.c | 3 ++- .../System.Native/pal_interfaceaddresses.c | 14 +++++++++---- .../System.Native/pal_networkstatistics.c | 4 +++- 7 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 936899066fae79..2eaf31ee684482 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -163,7 +163,9 @@ session_provider_tracepoint_register ( reg.name_args = (uint64_t)tracepoint->tracepoint_format; - if (ioctl(user_events_data_fd, DIAG_IOCSREG, ®) == -1) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(user_events_data_fd, DIAG_IOCSREG, ®)) && errno == EINTR); + if (ioctl_result == -1) return false; tracepoint->write_index = reg.write_index; @@ -185,7 +187,9 @@ session_provider_tracepoint_unregister ( unreg.disable_bit = EP_SESSION_PROVIDER_TRACEPOINT_ENABLE_BIT; unreg.disable_addr = (uint64_t)&tracepoint->enabled; - if (ioctl(user_events_data_fd, DIAG_IOCSUNREG, &unreg) == -1) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(user_events_data_fd, DIAG_IOCSUNREG, &unreg)) && errno == EINTR); + if (ioctl_result == -1) return false; return true; diff --git a/src/native/libs/System.IO.Ports.Native/pal_serial.c b/src/native/libs/System.IO.Ports.Native/pal_serial.c index f80d8655727239..e84db97d9451e9 100644 --- a/src/native/libs/System.IO.Ports.Native/pal_serial.c +++ b/src/native/libs/System.IO.Ports.Native/pal_serial.c @@ -24,7 +24,9 @@ intptr_t SystemIoPortsNative_SerialPortOpen(const char * name) return fd; } - if (ioctl(fd, TIOCEXCL) != 0) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(fd, TIOCEXCL)) && errno == EINTR); + if (ioctl_result != 0) { // We couldn't get exclusive access to the device file int oldErrno = errno; @@ -43,7 +45,7 @@ int SystemIoPortsNative_SerialPortClose(intptr_t handle) // preventing reopening after closing the handle // ignoring the error - best effort - ioctl(fd, TIOCNXCL); + while (-1 == ioctl(fd, TIOCNXCL) && errno == EINTR); return close(fd); } diff --git a/src/native/libs/System.IO.Ports.Native/pal_termios.c b/src/native/libs/System.IO.Ports.Native/pal_termios.c index 4b407423620527..03e680b3f8d296 100644 --- a/src/native/libs/System.IO.Ports.Native/pal_termios.c +++ b/src/native/libs/System.IO.Ports.Native/pal_termios.c @@ -56,7 +56,9 @@ static int32_t TermiosGetStatus(intptr_t handle) { int fd = ToFileDescriptor(handle); int status = 0; - if (ioctl(fd, TIOCMGET, &status) < 0) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(fd, TIOCMGET, &status)) && errno == EINTR); + if (ioctl_result < 0) { return -1; } @@ -143,7 +145,9 @@ int32_t SystemIoPortsNative_TermiosSetSignal(intptr_t handle, int32_t signal, in { status &= ~bit; } - return ioctl(fd, TIOCMSET, &status); + int ioctl_result; + while (-1 == (ioctl_result = ioctl(fd, TIOCMSET, &status)) && errno == EINTR); + return ioctl_result; } return -1; @@ -358,7 +362,9 @@ int32_t SystemIoPortsNative_TermiosSetSpeed(intptr_t handle, int32_t speed) // Looks like custom speed out of POSIX. Let see if we can set it via specialized call. #if HAVE_IOSS_H brate = speed; - if (ioctl(fd, IOSSIOSPEED, &brate) != -1) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(fd, IOSSIOSPEED, &brate)) && errno == EINTR); + if (ioctl_result != -1) { return speed; } @@ -394,7 +400,9 @@ int32_t SystemIoPortsNative_TermiosAvailableBytes(intptr_t handle, int32_t readB { int fd = ToFileDescriptor(handle); int32_t bytes; - if (ioctl (fd, readBuffer ? FIONREAD : TIOCOUTQ, &bytes) == -1) + int ioctl_result; + while (-1 == (ioctl_result = ioctl (fd, readBuffer ? FIONREAD : TIOCOUTQ, &bytes)) && errno == EINTR); + if (ioctl_result == -1) { return -1; } @@ -546,7 +554,9 @@ int32_t SystemIoPortsNative_TermiosReset(intptr_t handle, int32_t speed, int32_t #if HAVE_IOSS_H // We have deferred non-standard speed. brate = speed; - if (ioctl(fd, IOSSIOSPEED, &brate) == -1) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(fd, IOSSIOSPEED, &brate)) && errno == EINTR); + if (ioctl_result == -1) { return -1; } diff --git a/src/native/libs/System.IO.Ports.Native/pal_termios2.c b/src/native/libs/System.IO.Ports.Native/pal_termios2.c index d390cbd20c15ae..15b039fcb9c0e5 100644 --- a/src/native/libs/System.IO.Ports.Native/pal_termios2.c +++ b/src/native/libs/System.IO.Ports.Native/pal_termios2.c @@ -5,12 +5,15 @@ #include "pal_utilities.h" #include #include +#include #include int SystemIoPortsNative_Termios2SetSpeed(int fd, int speed) { struct termios2 tio2; - if (ioctl(fd, TCGETS2, &tio2) < 0) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(fd, TCGETS2, &tio2)) && errno == EINTR); + if (ioctl_result < 0) { return -1; } @@ -20,7 +23,8 @@ int SystemIoPortsNative_Termios2SetSpeed(int fd, int speed) tio2.c_ospeed = speed; tio2.c_ispeed = speed; - if (ioctl(fd, TCSETS2, &tio2) < 0) + while (-1 == (ioctl_result = ioctl(fd, TCSETS2, &tio2)) && errno == EINTR); + if (ioctl_result < 0) { return -1; } diff --git a/src/native/libs/System.Native/pal_console.c b/src/native/libs/System.Native/pal_console.c index aedd40ac8fe60a..6716d8cb77da87 100644 --- a/src/native/libs/System.Native/pal_console.c +++ b/src/native/libs/System.Native/pal_console.c @@ -24,7 +24,8 @@ int32_t SystemNative_GetWindowSize(intptr_t fd, WinSize* windowSize) assert(windowSize != NULL); #if HAVE_IOCTL && HAVE_TIOCGWINSZ - int error = ioctl(ToFileDescriptor(fd), TIOCGWINSZ, windowSize); + int error; + while (-1 == (error = ioctl(ToFileDescriptor(fd), TIOCGWINSZ, windowSize)) && errno == EINTR); if (error != 0) { diff --git a/src/native/libs/System.Native/pal_interfaceaddresses.c b/src/native/libs/System.Native/pal_interfaceaddresses.c index fe42cd91dac609..cc5d9b740fe6b5 100644 --- a/src/native/libs/System.Native/pal_interfaceaddresses.c +++ b/src/native/libs/System.Native/pal_interfaceaddresses.c @@ -275,7 +275,9 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, memset(&ifmr, 0, sizeof(ifmr)); strncpy(ifmr.ifm_name, actualName, sizeof(ifmr.ifm_name)); - if ((ioctl(fd, SIOCGIFMEDIA, (caddr_t)&ifmr) == 0) && (IFM_TYPE(ifmr.ifm_current) == IFM_IEEE80211)) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(fd, SIOCGIFMEDIA, (caddr_t)&ifmr)) && errno == EINTR); + if ((ioctl_result == 0) && (IFM_TYPE(ifmr.ifm_current) == IFM_IEEE80211)) { lla.HardwareType = NetworkInterfaceType_Wireless80211; } @@ -479,7 +481,9 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter if (socketfd > -1) { - if (ioctl(socketfd, SIOCGIFMTU, &ifr) == 0) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(socketfd, SIOCGIFMTU, &ifr)) && errno == EINTR); + if (ioctl_result == 0) { nii->Mtu = ifr.ifr_mtu; } @@ -493,7 +497,8 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter ecmd.cmd = ETHTOOL_GLINK; ifr.ifr_data = (char *) &ecmd; - if (ioctl(socketfd, SIOCETHTOOL, &ifr) == 0) + while (-1 == (ioctl_result = ioctl(socketfd, SIOCETHTOOL, &ifr)) && errno == EINTR); + if (ioctl_result == 0) { if (!ecmd.supported) { @@ -504,7 +509,8 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter // Try to get link speed if link is up. // Use older ETHTOOL_GSET instead of ETHTOOL_GLINKSETTINGS to support RH6 ecmd.cmd = ETHTOOL_GSET; - if (ioctl(socketfd, SIOCETHTOOL, &ifr) == 0) + while (-1 == (ioctl_result = ioctl(socketfd, SIOCETHTOOL, &ifr)) && errno == EINTR); + if (ioctl_result == 0) { #ifdef TARGET_ANDROID nii->Speed = (int64_t)ecmd.speed; diff --git a/src/native/libs/System.Native/pal_networkstatistics.c b/src/native/libs/System.Native/pal_networkstatistics.c index 27d3220e163a5a..45ec12f18a5648 100644 --- a/src/native/libs/System.Native/pal_networkstatistics.c +++ b/src/native/libs/System.Native/pal_networkstatistics.c @@ -658,7 +658,9 @@ int32_t SystemNative_GetNativeIPInterfaceStatistics(char* interfaceName, NativeI memset(&ifmr, 0, sizeof(ifmr)); strncpy(ifmr.ifm_name, interfaceName, sizeof(ifmr.ifm_name)); - if (ioctl(fd, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) + int ioctl_result; + while (-1 == (ioctl_result = ioctl(fd, SIOCGIFMEDIA, (caddr_t)&ifmr)) && errno == EINTR); + if (ioctl_result < 0) { if (errno == EOPNOTSUPP || errno == EINVAL) { From 8779bb6038029a0eb879264a61a813533bb19358 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:28:43 +1000 Subject: [PATCH 23/50] Ensure handling of all variants of `statfs` giving `EINTR` is consistent --- src/coreclr/gc/unix/cgroup.cpp | 3 ++- src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp | 3 ++- src/coreclr/pal/src/misc/cgroup.cpp | 3 ++- src/mono/mono/utils/mono-cgroup.c | 3 ++- src/native/libs/System.Native/pal_mount.c | 12 ++++++++---- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/coreclr/gc/unix/cgroup.cpp b/src/coreclr/gc/unix/cgroup.cpp index 8389e8692bf00d..356957a69dc717 100644 --- a/src/coreclr/gc/unix/cgroup.cpp +++ b/src/coreclr/gc/unix/cgroup.cpp @@ -124,7 +124,8 @@ class CGroup #else struct statfs stats; - int result = statfs("/sys/fs/cgroup", &stats); + int result; + while (-1 == (result = statfs("/sys/fs/cgroup", &stats)) && errno == EINTR); if (result != 0) return 0; diff --git a/src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp b/src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp index 7543c0aa2a53b9..b49336fa8e0b9f 100644 --- a/src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp @@ -95,7 +95,8 @@ class CGroup #else struct statfs stats; - int result = statfs("/sys/fs/cgroup", &stats); + int result; + while (-1 == (result = statfs("/sys/fs/cgroup", &stats)) && errno == EINTR); if (result != 0) return 0; diff --git a/src/coreclr/pal/src/misc/cgroup.cpp b/src/coreclr/pal/src/misc/cgroup.cpp index 427e9ef1301ff2..ebbd3fc1e9494f 100644 --- a/src/coreclr/pal/src/misc/cgroup.cpp +++ b/src/coreclr/pal/src/misc/cgroup.cpp @@ -88,7 +88,8 @@ class CGroup return 0; #else struct statfs stats; - int result = statfs("/sys/fs/cgroup", &stats); + int result; + while (-1 == (result = statfs("/sys/fs/cgroup", &stats)) && errno == EINTR); if (result != 0) return 0; diff --git a/src/mono/mono/utils/mono-cgroup.c b/src/mono/mono/utils/mono-cgroup.c index 4c58f53257b97e..20d2eba1334993 100644 --- a/src/mono/mono/utils/mono-cgroup.c +++ b/src/mono/mono/utils/mono-cgroup.c @@ -214,7 +214,8 @@ findCGroupVersion(void) struct statfs stats; - int result = statfs ("/sys/fs/cgroup", &stats); + int result; + while (-1 == (result = statfs("/sys/fs/cgroup", &stats)) && errno == EINTR); if (result != 0) return 0; diff --git a/src/native/libs/System.Native/pal_mount.c b/src/native/libs/System.Native/pal_mount.c index 758575e6954f33..e2c0f3a2d87d0f 100644 --- a/src/native/libs/System.Native/pal_mount.c +++ b/src/native/libs/System.Native/pal_mount.c @@ -102,12 +102,14 @@ int32_t SystemNative_GetSpaceInfoForMountPoint(const char* name, MountPointInfor struct statfs stats; memset(&stats, 0, sizeof(struct statfs)); - int result = statfs(name, &stats); + int result; + while (-1 == (result = statfs(name, &stats)) && errno == EINTR); #else struct statvfs stats; memset(&stats, 0, sizeof(struct statvfs)); - int result = statvfs(name, &stats); + int result; + while (-1 == (result = statvfs(name, &stats)) && errno == EINTR); #endif if (result == 0) { @@ -139,10 +141,12 @@ SystemNative_GetFileSystemTypeNameForMountPoint(const char* name, char* formatNa #if HAVE_NON_LEGACY_STATFS struct statfs stats; - int result = statfs(name, &stats); + int result; + while (-1 == (result = statfs(name, &stats)) && errno == EINTR); #else struct statvfs stats; - int result = statvfs(name, &stats); + int result; + while (-1 == (result = statvfs(name, &stats)) && errno == EINTR); #endif if (result == 0) From 36f241d57638dd871b380807dd0cca371aa1e155 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:30:50 +1000 Subject: [PATCH 24/50] Ensure handling of `sendmsg` giving `EINTR` is consistent --- src/native/libs/System.Native/pal_ifaddrs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/native/libs/System.Native/pal_ifaddrs.c b/src/native/libs/System.Native/pal_ifaddrs.c index 014b5b9d4521eb..d5d59ab932047e 100644 --- a/src/native/libs/System.Native/pal_ifaddrs.c +++ b/src/native/libs/System.Native/pal_ifaddrs.c @@ -137,7 +137,9 @@ static int send_netlink_dump_request(struct netlink_session *session, int type) session->message_header.msg_iovlen = 1; session->message_header.msg_iov = &session->payload_vector; - if (sendmsg(session->sock_fd, (const struct msghdr*)&session->message_header, 0) < 0) { + int sendmsg_result; + while (-1 == (sendmsg_result = sendmsg(session->sock_fd, (const struct msghdr*)&session->message_header, 0)) && errno == EINTR); + if (sendmsg_result < 0) { LOG_WARN("Failed to send netlink message. %s\n", strerror(errno)); return -1; } From dfd397292a1c383cda4fccdf23036beda620a1ba Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:32:56 +1000 Subject: [PATCH 25/50] Ensure handling of `accept` giving `EINTR` is consistent --- src/mono/mono/component/debugger-agent.c | 2 +- src/mono/mono/profiler/aot.c | 3 ++- src/mono/mono/profiler/log.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index ea283037a11df2..dbce6d6bac0db6 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -981,7 +981,7 @@ static SOCKET socket_transport_accept (SOCKET socket_fd) { MONO_REQ_GC_SAFE_MODE; - conn_fd = accept (socket_fd, NULL, NULL); + while (-1 == (conn_fd = accept (socket_fd, NULL, NULL)) && errno == EINTR); if (conn_fd == INVALID_SOCKET) { PRINT_ERROR_MSG ("debugger-agent: Unable to listen on %d: %s.\n", (int)socket_fd, strerror (get_last_sock_error())); diff --git a/src/mono/mono/profiler/aot.c b/src/mono/mono/profiler/aot.c index 3fd9128eb6b7d4..5702f80040b4ab 100644 --- a/src/mono/mono/profiler/aot.c +++ b/src/mono/mono/profiler/aot.c @@ -301,7 +301,8 @@ helper_thread (void *arg) break; if (FD_ISSET (aot_profiler.server_socket, &rfds)) { - SOCKET fd = accept (aot_profiler.server_socket, NULL, NULL); + SOCKET fd; + while (-1 == (fd = accept (aot_profiler.server_socket, NULL, NULL)) && errno == EINTR); if (fd != INVALID_SOCKET) { if (fd >= FD_SETSIZE) diff --git a/src/mono/mono/profiler/log.c b/src/mono/mono/profiler/log.c index 18803e7be67306..ab3eef0b49fa6c 100644 --- a/src/mono/mono/profiler/log.c +++ b/src/mono/mono/profiler/log.c @@ -2868,7 +2868,8 @@ helper_thread (void *arg) } if (FD_ISSET (log_profiler.server_socket, &rfds)) { - int fd = accept (log_profiler.server_socket, NULL, NULL); + int fd; + while (-1 == (fd = accept (log_profiler.server_socket, NULL, NULL)) && errno == EINTR); if (fd != -1) { #ifndef HOST_WIN32 From a395f6e57486ed66228940e10b2601bca83d0c36 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:36:09 +1000 Subject: [PATCH 26/50] Ensure handling of `connect` giving `EINTR` is consistent --- src/mono/mono/component/debugger-agent.c | 2 +- src/mono/mono/mini/cfgdump.c | 4 +++- src/mono/mono/profiler/log.c | 4 +++- src/native/libs/System.Native/pal_networking.c | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index dbce6d6bac0db6..a9fd60c85a1d76 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -1185,7 +1185,7 @@ socket_transport_connect (const char *address) setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)); } - res = connect (sfd, &sockaddr.addr, sock_len); + while (-1 == (res = connect (sfd, &sockaddr.addr, sock_len)) && errno == EINTR); if (res != SOCKET_ERROR) break; /* Success */ diff --git a/src/mono/mono/mini/cfgdump.c b/src/mono/mono/mini/cfgdump.c index 64e0377f45caa8..7d6142e21ea158 100644 --- a/src/mono/mono/mini/cfgdump.c +++ b/src/mono/mono/mini/cfgdump.c @@ -59,7 +59,9 @@ create_socket (const char *hostname, const int port) serv_addr.sin_port = htons (GINT_TO_UINT16 (port)); serv_addr.sin_addr.s_addr = inet_addr (hostname); - if (connect (sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + int connect_result; + while (-1 == (connect_result = connect (sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) && errno == EINTR); + if (connect_result < 0) { g_warning ("cfg_dump: Connect Failed: %s", strerror (errno)); return -2; } diff --git a/src/mono/mono/profiler/log.c b/src/mono/mono/profiler/log.c index ab3eef0b49fa6c..8d643dadaebe50 100644 --- a/src/mono/mono/profiler/log.c +++ b/src/mono/mono/profiler/log.c @@ -2522,7 +2522,9 @@ signal_helper_thread (char c) gulong non_blocking = 1; ioctlsocket (client_socket, FIONBIO, &non_blocking); - if (connect (client_socket, (SOCKADDR *)&client_addr, sizeof (client_addr)) == SOCKET_ERROR) { + int connect_result; + while (-1 == (connect_result = connect (client_socket, (SOCKADDR *)&client_addr, sizeof (client_addr))) && errno == EINTR); + if (connect_result == SOCKET_ERROR) { if (WSAGetLastError () == WSAEWOULDBLOCK) { fd_set wfds; int max_fd = -1; diff --git a/src/native/libs/System.Native/pal_networking.c b/src/native/libs/System.Native/pal_networking.c index e1a4f35f19d19f..9abebfe307d032 100644 --- a/src/native/libs/System.Native/pal_networking.c +++ b/src/native/libs/System.Native/pal_networking.c @@ -3540,7 +3540,7 @@ int32_t SystemNative_Disconnect(intptr_t socket) memset(&addr, 0, sizeof(addr)); addr.sa_family = AF_UNSPEC; - err = connect(fd, &addr, sizeof(addr)); + while (-1 == (err = connect(fd, &addr, sizeof(addr))) && errno == EINTR); if (err != 0) { // On some older kernels connect(AF_UNSPEC) may fail. Fall back to shutdown in these cases: From c79179150d5e760bbe9fab8b9ad452b207f6fe25 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:37:31 +1000 Subject: [PATCH 27/50] Ensure handling of `kevent` giving `EINTR` is consistent --- src/coreclr/pal/src/synchmgr/synchmanager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index 88ebb82c7370df..c459fdd18f9e53 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -1811,8 +1811,9 @@ namespace CorUnix iNChanges = 0; } - iRet = kevent(m_iKQueue, &keChanges, iNChanges, - &m_keProcessPipeEvent, 1, pts); + while (-1 == (iRet = kevent(m_iKQueue, &keChanges, iNChanges, + &m_keProcessPipeEvent, 1, pts)) + && errno == EINTR); if (0 < iRet) { From aa5f35ca0c476503f13601894ad48c626cf45648 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:45:44 +1000 Subject: [PATCH 28/50] Ensure handling of `dup2` giving `EINTR` is consistent --- src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp | 2 +- src/coreclr/pal/src/thread/process.cpp | 12 ++++++++---- src/mono/mono/mini/mini-posix.c | 2 +- src/native/external/libunwind/tests/test-ptrace.c | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp index 582774a94621c0..eec52317ebcdfd 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp @@ -250,7 +250,7 @@ CreateCrashDump( // Only dup the child's stderr if there is error buffer if (errorMessageBuffer != nullptr) { - dup2(child_pipe, STDERR_FILENO); + while (-1 == dup2(child_pipe, STDERR_FILENO) && errno == EINTR); } // Execute the createdump program if (execv(argv[0], (char* const *)argv) == -1) diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index ffaaae2a8823a8..70296c85aa7270 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -897,19 +897,23 @@ CorUnix::InternalCreateProcess( fd to the corresponding standard one. The API that I use, dup2, will copy the source to the destination, automatically closing the existing destination, in an atomic way */ - if (dup2(iFdIn, STDIN_FILENO) == -1) + int dup2_result; + while (-1 == (dup2_result = dup2(iFdIn, STDIN_FILENO)) && errno == EINTR); + if (dup2_result == -1) { // Didn't duplicate standard in. _exit(EXIT_FAILURE); } - if (dup2(iFdOut, STDOUT_FILENO) == -1) + while (-1 == (dup2_result = dup2(iFdOut, STDOUT_FILENO)) && errno == EINTR); + if (dup2_result == -1) { // Didn't duplicate standard out. _exit(EXIT_FAILURE); } - if (dup2(iFdErr, STDERR_FILENO) == -1) + while (-1 == (dup2_result = dup2(iFdErr, STDERR_FILENO)) && errno == EINTR); + if (dup2_result == -1) { // Didn't duplicate standard error. _exit(EXIT_FAILURE); @@ -2254,7 +2258,7 @@ PROCCreateCrashDump( // Only dup the child's stderr if there is error buffer if (errorMessageBuffer != nullptr) { - dup2(child_pipe, STDERR_FILENO); + while (-1 == dup2(child_pipe, STDERR_FILENO) && errno == EINTR); } if (g_createdumpCallback != nullptr) { diff --git a/src/mono/mono/mini/mini-posix.c b/src/mono/mono/mini/mini-posix.c index 5a13d797dd88ae..17d41923c8ead9 100644 --- a/src/mono/mono/mini/mini-posix.c +++ b/src/mono/mono/mini/mini-posix.c @@ -865,7 +865,7 @@ dump_native_stacktrace (const char *signal, MonoContext *mctx) #endif if (!mini_debug_options.no_gdb_backtrace && pid == 0) { - dup2 (STDERR_FILENO, STDOUT_FILENO); + while (-1 == dup2 (STDERR_FILENO, STDOUT_FILENO) && errno == EINTR); g_async_safe_printf ("\n=================================================================\n"); g_async_safe_printf("\tExternal Debugger Dump:\n"); diff --git a/src/native/external/libunwind/tests/test-ptrace.c b/src/native/external/libunwind/tests/test-ptrace.c index bfd45bf9aafb98..d1cfbb4c165bce 100644 --- a/src/native/external/libunwind/tests/test-ptrace.c +++ b/src/native/external/libunwind/tests/test-ptrace.c @@ -234,7 +234,7 @@ main (int argc, char **argv) /* child */ if (!verbose) - dup2 (open ("/dev/null", O_WRONLY), 1); + while (-1 == dup2 (open ("/dev/null", O_WRONLY), 1) && errno == EINTR); #if HAVE_DECL_PTRACE_TRACEME long stat = ptrace (PTRACE_TRACEME, 0, 0, 0); From 400e7f6bb487cf2b6394366693184797dc1959a1 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 8 Jul 2025 13:54:07 +1000 Subject: [PATCH 29/50] Ensure handling of `remove` giving `EINTR` is consistent - Skipped tests - Excludes potential changes to external libs: libeventheader-tracepoint, libunwind --- src/coreclr/debug/createdump/crashreportwriter.cpp | 2 +- src/coreclr/debug/createdump/createdumpunix.cpp | 2 +- src/coreclr/ilasm/main.cpp | 3 ++- src/coreclr/tools/superpmi/mcs/verbmerge.cpp | 4 +++- src/coreclr/tools/superpmi/superpmi-shared/logging.cpp | 4 +++- src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp | 9 +++++---- src/mono/mono/component/debugger-agent.c | 2 +- src/native/corehost/hostmisc/pal.h | 8 +++++++- src/native/external/libunwind/tests/test-ptrace.c | 2 +- 9 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/coreclr/debug/createdump/crashreportwriter.cpp b/src/coreclr/debug/createdump/crashreportwriter.cpp index 5a90e55c11273c..0ebb8b9f2dd613 100644 --- a/src/coreclr/debug/createdump/crashreportwriter.cpp +++ b/src/coreclr/debug/createdump/crashreportwriter.cpp @@ -48,7 +48,7 @@ CrashReportWriter::WriteCrashReport(const std::string& dumpFileName) printf_error("Writing the crash report file FAILED\n"); // Delete the partial json file on error - remove(crashReportFile.c_str()); + while (-1 == remove(crashReportFile.c_str()) && errno == EINTR); } } diff --git a/src/coreclr/debug/createdump/createdumpunix.cpp b/src/coreclr/debug/createdump/createdumpunix.cpp index ea6fa5b8b94d48..d9d030805afffe 100644 --- a/src/coreclr/debug/createdump/createdumpunix.cpp +++ b/src/coreclr/debug/createdump/createdumpunix.cpp @@ -91,7 +91,7 @@ CreateDump(const CreateDumpOptions& options) printf_error("Writing dump FAILED\n"); // Delete the partial dump file on error - remove(dumpPath.c_str()); + while (-1 == remove(dumpPath.c_str()) && errno == EINTR); goto exit; } } diff --git a/src/coreclr/ilasm/main.cpp b/src/coreclr/ilasm/main.cpp index 58e0ee7573aa69..337a57091d05b7 100644 --- a/src/coreclr/ilasm/main.cpp +++ b/src/coreclr/ilasm/main.cpp @@ -11,6 +11,7 @@ #include "clrversion.h" #include "strsafe.h" +#include #define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS((expr)) WCHAR* EqualOrColon(_In_ __nullterminated WCHAR* szArg) @@ -844,7 +845,7 @@ extern "C" int _cdecl wmain(int argc, _In_ WCHAR **argv) MAKE_UTF8PTR_FROMWIDE_NOTHROW(szOutputFilename, wzOutputFilename); if (szOutputFilename != NULL) { - remove(szOutputFilename); + while (-1 == remove(szOutputFilename) && errno == EINTR); } #endif } diff --git a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp index 2f3aa9b65948b3..b1986fd8c0cf7a 100644 --- a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp +++ b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp @@ -6,6 +6,7 @@ #include "simpletimer.h" #include "logging.h" #include "spmiutil.h" +#include #include #ifdef TARGET_UNIX #include @@ -678,7 +679,8 @@ int verbMerge::DoWork(const char* nameOfOutputFile, const char* pattern, bool re if (result != 0) { // There was a failure. Delete the output file, to avoid leaving some half-created file. - int st = remove(nameOfOutputFile); + int st; + while (-1 == (st = remove(nameOfOutputFile)) && errno == EINTR); if (st != 0) { LogError("Failed to delete file after MCS /merge failed. GetLastError()=%u", GetLastError()); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp b/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp index 63b2c5ee4a1121..b50e635157c4cb 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp @@ -86,7 +86,9 @@ void Logger::CloseLogFile() { // We can call this before closing the handle because remove just marks the file // for deletion, i.e. it does not actually get deleted until its last handle is closed. - if (remove(s_logFilePath) == -1) + int remove_result; + while (-1 == (remove_result = remove(s_logFilePath)) && errno == EINTR); + if (remove_result == -1) fprintf(stderr, "WARNING: [Logger::CloseLogFile] remove failed. GetLastError()=%u\n", GetLastError()); } diff --git a/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp b/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp index 07b3cd5805bcb9..40815af7f1b81c 100644 --- a/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp @@ -9,6 +9,7 @@ #include "commandline.h" #include "errorhandling.h" #include "fileio.h" +#include #include // Forward declare the conversion method. Including spmiutil.h pulls in other headers @@ -763,14 +764,14 @@ int doParallelSuperPMI(CommandLine::Options& o) PerWorkerData& wd = perWorkerData[i]; if (wd.failingMCListPath != nullptr) { - remove(wd.failingMCListPath); + while (-1 == remove(wd.failingMCListPath) && errno == EINTR); } if (wd.detailsPath != nullptr) { - remove(wd.detailsPath); + while (-1 == remove(wd.detailsPath) && errno == EINTR); } - remove(wd.stdOutputPath); - remove(wd.stdErrorPath); + while (-1 == remove(wd.stdOutputPath) && errno == EINTR); + while (-1 == remove(wd.stdErrorPath) && errno == EINTR); } } diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index a9fd60c85a1d76..4604e47be397e1 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -874,7 +874,7 @@ mono_debugger_agent_cleanup (void) mono_de_cleanup (); if (file_check_valid_memory != -1) { - remove (filename_check_valid_memory); + while (-1 == remove (filename_check_valid_memory) && errno == EINTR); g_free (filename_check_valid_memory); close (file_check_valid_memory); } diff --git a/src/native/corehost/hostmisc/pal.h b/src/native/corehost/hostmisc/pal.h index 42ed0782493278..e86e83aaa00528 100644 --- a/src/native/corehost/hostmisc/pal.h +++ b/src/native/corehost/hostmisc/pal.h @@ -272,7 +272,13 @@ namespace pal return result; } - inline int remove(const char_t* path) { return ::remove(path); } + inline int remove(const char_t* path) + { + int result; + while (-1 == (result = ::remove(path)) && errno == EINTR); + return result; + } + inline bool munmap(void* addr, size_t length) { return ::munmap(addr, length) == 0; } inline int get_pid() { return getpid(); } inline void sleep(uint32_t milliseconds) { usleep(milliseconds * 1000); } diff --git a/src/native/external/libunwind/tests/test-ptrace.c b/src/native/external/libunwind/tests/test-ptrace.c index d1cfbb4c165bce..bfd45bf9aafb98 100644 --- a/src/native/external/libunwind/tests/test-ptrace.c +++ b/src/native/external/libunwind/tests/test-ptrace.c @@ -234,7 +234,7 @@ main (int argc, char **argv) /* child */ if (!verbose) - while (-1 == dup2 (open ("/dev/null", O_WRONLY), 1) && errno == EINTR); + dup2 (open ("/dev/null", O_WRONLY), 1); #if HAVE_DECL_PTRACE_TRACEME long stat = ptrace (PTRACE_TRACEME, 0, 0, 0); From d5024c58e3e7bb93d82ec62d8ca6823e829dff73 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 18 Jul 2025 13:31:29 +1000 Subject: [PATCH 30/50] Ensure handling of `lseek` & variants giving `EINTR` is consistent --- src/coreclr/debug/createdump/crashinfo.cpp | 5 +++-- src/coreclr/pal/src/file/file.cpp | 12 +++++++----- src/coreclr/pal/src/map/map.cpp | 9 ++++++--- .../pal/src/sharedmemory/sharedmemory.cpp | 13 ++++++++++--- .../threading/NamedMutex/test1/nopal.cpp | 4 +++- .../mono/eventpipe/ep-rt-mono-runtime-provider.c | 4 +++- src/mono/mono/utils/mono-filemap.c | 9 ++++++--- src/native/libs/System.Native/pal_networking.c | 16 +++++++++++++--- 8 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index 8958cfc05c54f3..b0863cceb51d0d 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -814,8 +814,9 @@ CrashInfo::PageMappedToPhysicalMemory(uint64_t start) } uint64_t pagemapOffset = (start / PAGE_SIZE) * sizeof(uint64_t); - uint64_t seekResult = lseek(m_fdPagemap, (off_t) pagemapOffset, SEEK_SET); - if (seekResult != pagemapOffset) + int64_t seekResult; + while (-1 == (seekResult = lseek(m_fdPagemap, (off_t) pagemapOffset, SEEK_SET)) && errno == EINTR); + if ((uint64_t)seekResult != pagemapOffset) { int seekErrno = errno; TRACE("Seeking in pagemap file FAILED, addr: %" PRIA PRIx ", pagemap offset: %" PRIA PRIx ", ERRNO %d: %s\n", start, pagemapOffset, seekErrno, strerror(seekErrno)); diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 88f1d7f6247d8d..58d82dbaad3683 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -1481,7 +1481,7 @@ InternalSetFilePointerForUnixFd( /* store the current position, in case the lseek moves the pointer before the beginning of the file */ - old_offset = lseek(iUnixFd, 0, SEEK_CUR); + while (-1 == (old_offset = lseek(iUnixFd, 0, SEEK_CUR)) && errno == EINTR); if (old_offset == -1) { ERROR("lseek(fd,0,SEEK_CUR) failed errno:%d (%s)\n", @@ -1525,9 +1525,11 @@ InternalSetFilePointerForUnixFd( } } - seek_res = (int64_t)lseek( iUnixFd, - seek_offset, - seek_whence ); + while (-1 == ( + seek_res = (int64_t)lseek( iUnixFd, + seek_offset, + seek_whence ) + ) && errno == EINTR); if ( seek_res < 0 ) { /* lseek() returns -1 on error, but also can seek to negative @@ -1535,7 +1537,7 @@ InternalSetFilePointerForUnixFd( -1. Win32 doesn't allow negative file offsets, so either case is an error. */ ERROR("lseek failed errno:%d (%s)\n", errno, strerror(errno)); - lseek(iUnixFd, old_offset, SEEK_SET); + while (-1 == lseek(iUnixFd, old_offset, SEEK_SET) && errno == EINTR); palError = ERROR_ACCESS_DENIED; } else diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 963f8dcf3310b7..8078b2e2c49912 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -1506,8 +1506,11 @@ static PAL_ERROR MAPGrowLocalFile( INT UnixFD, off_t NewSize ) TRACE( "Trying the less efficient way.\n" ); - CurrentPosition = lseek( UnixFD, 0, SEEK_CUR ); - OrigSize = lseek( UnixFD, 0, SEEK_END ); + off_t lseek_result; + while (-1 == (lseek_result lseek( UnixFD, 0, SEEK_CUR )) && errno == EINTR); + CurrentPosition = lseek_result; + while (-1 == (lseek_result lseek( UnixFD, 0, SEEK_END )) && errno == EINTR); + OrigSize = lseek_result; if ( OrigSize == -1 ) { ERROR( "Unable to locate the EOF marker. Reason=%s\n", @@ -1566,7 +1569,7 @@ static PAL_ERROR MAPGrowLocalFile( INT UnixFD, off_t NewSize ) } /* restore the file pointer position */ - lseek( UnixFD, CurrentPosition, SEEK_SET ); + while (-1 == lseek( UnixFD, CurrentPosition, SEEK_SET ) && errno == EINTR); } done: diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 77c590b5c90119..9295949204ca01 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -616,9 +616,16 @@ SIZE_T SharedMemoryHelpers::GetFileSize(SharedMemorySystemCallErrors *errors, LP _ASSERTE(filePath[0] != '\0'); _ASSERTE(fileDescriptor != -1); - off_t endOffset = lseek(fileDescriptor, 0, SEEK_END); - if (endOffset == static_cast(-1) || - lseek(fileDescriptor, 0, SEEK_SET) == static_cast(-1)) + off_t endOffset; + while (-1 == (endOffset = lseek(fileDescriptor, 0, SEEK_END)) && errno == EINTR); + bool condition = endOffset == static_cast(-1); + if (!condition) + { + off_t lseek_result; + while (-1 == (lseek_result = lseek(fileDescriptor, 0, SEEK_SET)) && errno == EINTR); + if (lseek_result == static_cast(-1)) condition = true; + } + if (condition) { if (errors != nullptr) { diff --git a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp index 6a7bac56c2146c..c974061a1e44fa 100644 --- a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp +++ b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp @@ -75,7 +75,9 @@ bool WriteHeaderInfo(const char *path, bool currentUserOnly, char sharedMemoryTy while (-1 == (result = ftruncate(fd, getpagesize())) && errno == EINTR); if (result != 0) return false; - if (lseek(fd, 0, SEEK_SET) != 0) + off_t lseek_result; + while (-1 == (lseek_result = lseek(fd, 0, SEEK_SET)) && errno == EINTR); + if (lseek_result != 0) return false; // See SharedMemorySharedDataHeader for format diff --git a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c index 2fff49357e844c..5a842c940c2958 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c +++ b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c @@ -3386,7 +3386,9 @@ gc_heap_dump_mem_file_buffer_reset_func (void *context) EP_ASSERT (file_buffer->fd != -1); result &= gc_heap_dump_mem_file_buffer_flush (file_buffer); - result &= g_lseek (file_buffer->fd, 0, SEEK_SET) != -1; + off_t lseek_result; + while (-1 == (lseek_result = g_lseek (file_buffer->fd, 0, SEEK_SET)) && errno == EINTR); + result &= lseek_result != -1; return result; } diff --git a/src/mono/mono/utils/mono-filemap.c b/src/mono/mono/utils/mono-filemap.c index e4858d1be87ffd..85a5972ee3013f 100644 --- a/src/mono/mono/utils/mono-filemap.c +++ b/src/mono/mono/utils/mono-filemap.c @@ -91,20 +91,23 @@ mono_file_map_set_allocator (mono_file_map_alloc_fn alloc, mono_file_map_release void * mono_file_map_fileio (size_t length, int flags, int fd, guint64 offset, void **ret_handle) { + off_t lseek_result; guint64 cur_offset; size_t bytes_read; void *ptr = (*alloc_fn) (length); if (!ptr) return NULL; - cur_offset = lseek (fd, 0, SEEK_CUR); - if (lseek (fd, offset, SEEK_SET) != offset) { + while (-1 == (lseek_result = lseek (fd, 0, SEEK_CUR)) && errno == EINTR); + while (-1 == (lseek_result = lseek (fd, offset, SEEK_SET)) && errno == EINTR); + cur_offset = lseek_result; + if (cur_offset != offset) { (*release_fn) (ptr); return NULL; } bytes_read = read (fd, ptr, length); if (bytes_read != length) return NULL; - lseek (fd, cur_offset, SEEK_SET); + while (-1 == lseek (fd, cur_offset, SEEK_SET) && errno == EINTR); *ret_handle = NULL; return ptr; } diff --git a/src/native/libs/System.Native/pal_networking.c b/src/native/libs/System.Native/pal_networking.c index 9abebfe307d032..0cd1dcaa881ae1 100644 --- a/src/native/libs/System.Native/pal_networking.c +++ b/src/native/libs/System.Native/pal_networking.c @@ -3629,8 +3629,16 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i char* buffer = NULL; // Save the original input file position and seek to the offset position - off_t inputFileOrigOffset = lseek(infd, 0, SEEK_CUR); - if (inputFileOrigOffset == -1 || lseek(infd, offtOffset, SEEK_SET) == -1) + off_t inputFileOrigOffset; + while (-1 == (inputFileOrigOffset = lseek(infd, 0, SEEK_CUR)) && errno == EINTR); + bool condition = inputFileOrigOffset == -1; + if (!condition) + { + off_t lseek_result; + while (-1 == (lseek_result = lseek(infd, offtOffset, SEEK_SET)) && errno == EINTR); + if (lseek_result == -1) condition = true; + } + if (condition) { goto error; } @@ -3680,7 +3688,9 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i } // Restore the original input file position - if (lseek(infd, inputFileOrigOffset, SEEK_SET) == -1) + off_t lseek_result; + while (-1 == (lseek_result = lseek(infd, inputFileOrigOffset, SEEK_SET)) && errno == EINTR); + if (lseek_result == -1) { goto error; } From 143d9ce67675dfad780f189df485394a016a781f Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 18 Jul 2025 13:50:12 +1000 Subject: [PATCH 31/50] Ensure handling of `open` & variants giving `EINTR` is consistent - Excludes potential changes to "templates" --- src/coreclr/debug/createdump/crashinfounix.cpp | 7 ++++--- src/coreclr/debug/createdump/crashreportwriter.cpp | 2 +- src/coreclr/debug/createdump/dumpwriter.cpp | 2 +- src/coreclr/debug/debug-pal/unix/twowaypipe.cpp | 8 ++++---- src/coreclr/hosts/corerun/corerun.hpp | 3 ++- src/coreclr/pal/src/thread/thread.cpp | 2 +- .../palsuite/threading/NamedMutex/test1/nopal.cpp | 6 ++++-- src/mono/mono/component/debugger-agent.c | 2 +- src/mono/mono/eglib/gfile-posix.c | 2 +- src/mono/mono/sgen/sgen-protocol.c | 2 +- src/mono/mono/utils/dlmalloc.c | 10 ++++++++-- src/mono/mono/utils/mono-filemap.c | 3 ++- src/mono/mono/utils/mono-mmap.c | 3 ++- src/mono/mono/utils/mono-proclib.c | 3 ++- src/native/corehost/hostmisc/pal.unix.cpp | 6 ++++-- src/native/minipal/debugger.c | 5 +++-- .../AndroidAppBuilder/Templates/monodroid-coreclr.c | 3 ++- 17 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfounix.cpp b/src/coreclr/debug/createdump/crashinfounix.cpp index 32bb7ff8a15112..1d7226a2c7affa 100644 --- a/src/coreclr/debug/createdump/crashinfounix.cpp +++ b/src/coreclr/debug/createdump/crashinfounix.cpp @@ -25,7 +25,7 @@ CrashInfo::Initialize() return false; } - m_fdMem = open(memPath, O_RDONLY); + while (-1 == (m_fdMem = open(memPath, O_RDONLY)) && errno == EINTR); if (m_fdMem == -1) { int err = errno; @@ -54,7 +54,7 @@ CrashInfo::Initialize() printf_error("snprintf failed building /proc//pagemap name\n"); return false; } - m_fdPagemap = open(pagemapPath, O_RDONLY); + while (-1 == (m_fdPagemap = open(pagemapPath, O_RDONLY)) && errno == EINTR); if (m_fdPagemap == -1) { TRACE("open(%s) FAILED %d (%s), will fallback to dumping all memory regions without checking if they are committed\n", pagemapPath, errno, strerror(errno)); @@ -176,7 +176,8 @@ CrashInfo::GetAuxvEntries() printf_error("snprintf failed building /proc//auxv\n"); return false; } - int fd = open(auxvPath, O_RDONLY, 0); + int fd; + while (-1 == (fd = open(auxvPath, O_RDONLY, 0)) && errno == EINTR); if (fd == -1) { printf_error("Problem reading aux info: open(%s) FAILED %s (%d)\n", auxvPath, strerror(errno), errno); diff --git a/src/coreclr/debug/createdump/crashreportwriter.cpp b/src/coreclr/debug/createdump/crashreportwriter.cpp index 0ebb8b9f2dd613..8e4c89f5ae6b2e 100644 --- a/src/coreclr/debug/createdump/crashreportwriter.cpp +++ b/src/coreclr/debug/createdump/crashreportwriter.cpp @@ -270,7 +270,7 @@ CrashReportWriter::WriteStackFrame(const StackFrame& frame) bool CrashReportWriter::OpenWriter(const char* fileName) { - m_fd = open(fileName, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR | S_IRUSR); + while (-1 == (m_fd = open(fileName, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR | S_IRUSR)) && errno == EINTR); if (m_fd == -1) { printf_error("Could not create json file '%s': %s (%d)\n", fileName, strerror(errno), errno); diff --git a/src/coreclr/debug/createdump/dumpwriter.cpp b/src/coreclr/debug/createdump/dumpwriter.cpp index 0e39b52b3a7d4c..6e68ae4fd41c63 100644 --- a/src/coreclr/debug/createdump/dumpwriter.cpp +++ b/src/coreclr/debug/createdump/dumpwriter.cpp @@ -23,7 +23,7 @@ DumpWriter::~DumpWriter() bool DumpWriter::OpenDump(const char* dumpFileName) { - m_fd = open(dumpFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR | S_IRUSR); + while (-1 == (m_fd = open(dumpFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR | S_IRUSR)) && errno == EINTR); if (m_fd == -1) { printf_error("Could not create output file '%s': %s (%d)\n", dumpFileName, strerror(errno), errno); diff --git a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp index a140a559d332d0..9ca6509b48eda2 100644 --- a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp +++ b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp @@ -61,13 +61,13 @@ bool TwoWayPipe::Connect(const ProcessDescriptor& pd) // Pipe opening order is reversed compared to WaitForConnection() // in order to avoid deadlock. - m_outboundPipe = open(m_outPipeName, O_WRONLY); + while (-1 == (m_outboundPipe = open(m_outPipeName, O_WRONLY)) && errno == EINTR); if (m_outboundPipe == INVALID_PIPE) { return false; } - m_inboundPipe = open(m_inPipeName, O_RDONLY); + while (-1 == (m_inboundPipe = open(m_inPipeName, O_RDONLY)) && errno == EINTR); if (m_inboundPipe == INVALID_PIPE) { close(m_outboundPipe); @@ -88,13 +88,13 @@ bool TwoWayPipe::WaitForConnection() if (m_state != Created) return false; - m_inboundPipe = open(m_inPipeName, O_RDONLY); + while (-1 == (m_inboundPipe = open(m_inPipeName, O_RDONLY)) && errno == EINTR); if (m_inboundPipe == INVALID_PIPE) { return false; } - m_outboundPipe = open(m_outPipeName, O_WRONLY); + while (-1 == (m_outboundPipe = open(m_outPipeName, O_WRONLY)) && errno == EINTR); if (m_outboundPipe == INVALID_PIPE) { close(m_inboundPipe); diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 3cda5c257e0c13..e981f00f1cba4c 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -467,7 +467,8 @@ namespace pal inline bool try_map_file_readonly(const char* path, void** mapped, int64_t* size) { - int fd = open(path, O_RDONLY); + int fd; + while (-1 == (fd = open(path, O_RDONLY)) && errno == EINTR); if (fd == -1) return false; diff --git a/src/coreclr/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index fe48f04dfe639b..fc58d9ded6c58e 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -1380,7 +1380,7 @@ CorUnix::GetThreadTimesInternal( int readResult; char statusFilename[64]; snprintf(statusFilename, sizeof(statusFilename), "/proc/%d/lwp/%d/lwpstatus", getpid(), pTargetThread->GetLwpId()); - fd = open(statusFilename, O_RDONLY); + while (-1 == (fd = open(statusFilename, O_RDONLY)) && errno == EINTR); if (fd == -1) { ASSERT("open(%s) failed; errno is %d (%s)\n", statusFilename, errno, strerror(errno)); diff --git a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp index c974061a1e44fa..6d58b0b5ad4b4d 100644 --- a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp +++ b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp @@ -45,7 +45,8 @@ int test_kill(unsigned int pid) bool TestFileExists(const char *path) { - int fd = open(path, O_RDWR); + int fd; + while (-1 == (fd = open(path, O_RDWR)) && errno == EINTR); if (fd == -1) return false; close(fd); @@ -54,7 +55,8 @@ bool TestFileExists(const char *path) bool WriteHeaderInfo(const char *path, bool currentUserOnly, char sharedMemoryType, char version, int *fdRef) { - int fd = open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + int fd; + while (-1 == (fd = open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) && errno == EINTR); if (fd == -1) return false; diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index 4604e47be397e1..342f82b550adb7 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -7054,7 +7054,7 @@ create_file_to_check_memory_address (void) return; char *file_name = g_strdup_printf ("debugger_check_valid_memory.%d", mono_process_current_pid ()); filename_check_valid_memory = g_build_filename (g_get_tmp_dir (), file_name, (const char*)NULL); - file_check_valid_memory = open(filename_check_valid_memory, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR); + while (-1 == (file_check_valid_memory = open(filename_check_valid_memory, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR)) && errno == EINTR); g_free (file_name); } diff --git a/src/mono/mono/eglib/gfile-posix.c b/src/mono/mono/eglib/gfile-posix.c index 686e0f4b22a2a6..c9fff0d3172fed 100644 --- a/src/mono/mono/eglib/gfile-posix.c +++ b/src/mono/mono/eglib/gfile-posix.c @@ -66,7 +66,7 @@ g_file_get_contents (const gchar *filename, gchar **contents, gsize *length, GEr if (length) *length = 0; - fd = open (filename, OPEN_FLAGS); + while (-1 == (fd = open (filename, OPEN_FLAGS)) && errno == EINTR); if (fd == -1) { if (gerror != NULL) { int err = errno; diff --git a/src/mono/mono/sgen/sgen-protocol.c b/src/mono/mono/sgen/sgen-protocol.c index 4e508a6d38b932..dff8a8526594f5 100644 --- a/src/mono/mono/sgen/sgen-protocol.c +++ b/src/mono/mono/sgen/sgen-protocol.c @@ -102,7 +102,7 @@ binary_protocol_open_file (gboolean assert_on_failure) binary_protocol_file = CreateFileA (filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); #elif defined(HAVE_UNISTD_H) do { - binary_protocol_file = open (filename, O_CREAT | O_WRONLY, 0644); + while (-1 == (binary_protocol_file = open (filename, O_CREAT | O_WRONLY, 0644)) && errno == EINTR); if (binary_protocol_file == -1) { if (errno != EINTR) break; /* Failed */ diff --git a/src/mono/mono/utils/dlmalloc.c b/src/mono/mono/utils/dlmalloc.c index 53fbd2adf2bf85..c993521b903b91 100644 --- a/src/mono/mono/utils/dlmalloc.c +++ b/src/mono/mono/utils/dlmalloc.c @@ -1322,8 +1322,13 @@ extern void* sbrk(ptrdiff_t); */ #define MMAP_FLAGS (MAP_PRIVATE) static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ +static int open_with_eintr_handling(const char *path, int oflag) { + int open_result; + while (-1 == (open_result = open(path, oflag)) && errno == EINTR); + return open_result; +} #define CALL_MMAP(s) ((dev_zero_fd < 0) ? \ - (dev_zero_fd = open("/dev/zero", O_RDWR), \ + (dev_zero_fd = open_with_eintr_handling("/dev/zero", O_RDWR), \ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) #endif /* MAP_ANONYMOUS */ @@ -2455,7 +2460,8 @@ static int init_mparams(void) { int fd; unsigned char buf[sizeof(size_t)]; /* Try to use /dev/urandom, else fall back on using time */ - if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && + while (-1 == (fd = open("/dev/urandom", O_RDONLY)) && errno == EINTR); + if (fd >= 0 && read(fd, buf, sizeof(buf)) == sizeof(buf)) { s = *((size_t *) buf); close(fd); diff --git a/src/mono/mono/utils/mono-filemap.c b/src/mono/mono/utils/mono-filemap.c index 85a5972ee3013f..a2a7e53037e7cb 100644 --- a/src/mono/mono/utils/mono-filemap.c +++ b/src/mono/mono/utils/mono-filemap.c @@ -38,7 +38,8 @@ mono_file_map_open (const char* name) g_free (wname); return result; #else - int fd = open (name, O_RDONLY); + int fd; + while (-1 == (fd = open (name, O_RDONLY)) && errno == EINTR); if (fd < 0) return NULL; return (MonoFileMap *)(size_t)fd; diff --git a/src/mono/mono/utils/mono-mmap.c b/src/mono/mono/utils/mono-mmap.c index 09af6f8994b942..c0e0e8f50a0548 100644 --- a/src/mono/mono/utils/mono-mmap.c +++ b/src/mono/mono/utils/mono-mmap.c @@ -298,7 +298,8 @@ mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type) BEGIN_CRITICAL_SECTION; ptr = mmap (addr, length, prot, mflags, -1, 0); if (ptr == MAP_FAILED) { - int fd = open ("/dev/zero", O_RDONLY); + int fd; + while (-1 == (fd = open ("/dev/zero", O_RDONLY)) && errno == EINTR); if (fd != -1) { ptr = mmap (addr, length, prot, mflags, fd, 0); close (fd); diff --git a/src/mono/mono/utils/mono-proclib.c b/src/mono/mono/utils/mono-proclib.c index 0daec1915691c0..a24932d7f936d1 100644 --- a/src/mono/mono/utils/mono-proclib.c +++ b/src/mono/mono/utils/mono-proclib.c @@ -83,7 +83,8 @@ mono_cpu_count (void) */ int count = 0; char buffer[8] = {'\0'}; - int present = open ("/sys/devices/system/cpu/present", O_RDONLY); + int present; + while (-1 == (present = open ("/sys/devices/system/cpu/present", O_RDONLY)) && errno == EINTR); /* Format of the /sys entry is a cpulist of indexes which in the case * of present is always of the form "0-(n-1)" when there is more than * 1 core, n being the number of CPU cores in the system. Otherwise diff --git a/src/native/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp index 4b08394baa286b..1530cd6bfade1d 100644 --- a/src/native/corehost/hostmisc/pal.unix.cpp +++ b/src/native/corehost/hostmisc/pal.unix.cpp @@ -61,7 +61,8 @@ pal::string_t pal::get_timestamp() bool pal::touch_file(const pal::string_t& path) { - int fd = open(path.c_str(), (O_CREAT | O_EXCL), (S_IRUSR | S_IRGRP | S_IROTH)); + int fd; + while (-1 == (fd = open(path.c_str(), (O_CREAT | O_EXCL), (S_IRUSR | S_IRGRP | S_IROTH))) && errno == EINTR); if (fd == -1) { trace::warning(_X("open(%s) failed in %s"), path.c_str(), _STRINGIFY(__FUNCTION__)); @@ -73,7 +74,8 @@ bool pal::touch_file(const pal::string_t& path) static void* map_file(const pal::string_t& path, size_t* length, int prot, int flags) { - int fd = open(path.c_str(), O_RDONLY); + int fd; + while (-1 == (fd = open(path.c_str(), O_RDONLY)) && errno == EINTR); if (fd == -1) { trace::error(_X("Failed to map file. open(%s) failed with error %d"), path.c_str(), errno); diff --git a/src/native/minipal/debugger.c b/src/native/minipal/debugger.c index 4fdef053a225a3..22c720298ec103 100644 --- a/src/native/minipal/debugger.c +++ b/src/native/minipal/debugger.c @@ -64,7 +64,8 @@ bool minipal_is_native_debugger_present(void) bool debugger_present = false; char buf[2048]; - int status_fd = open("/proc/self/status", O_RDONLY); + int status_fd; + while (-1 == (status_fd = open("/proc/self/status", O_RDONLY)) && errno == EINTR); if (status_fd == -1) { return false; @@ -125,7 +126,7 @@ bool minipal_is_native_debugger_present(void) int fd; char statusFilename[64]; snprintf(statusFilename, sizeof(statusFilename), "/proc/%d/status", getpid()); - fd = open(statusFilename, O_RDONLY); + while (-1 == (fd = open(statusFilename, O_RDONLY)) && errno == EINTR); if (fd == -1) { return false; diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c b/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c index f973a886c9555a..8d35867665d470 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c @@ -118,7 +118,8 @@ external_assembly_probe(const char* name, void** data, int64_t* size) if (res < 0 || res != path_len) return false; - int fd = open(full_path, O_RDONLY); + int fd; + while (-1 == (fd = open(full_path, O_RDONLY)) && errno == EINTR); if (fd == -1) return false; From 3aa031fdafe5d01f9c6718feacee6bc223a1d7c9 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Wed, 30 Jul 2025 11:19:14 +1000 Subject: [PATCH 32/50] Ensure we handle `EINTR` & partial operations more consistently for `write` & variants - Excludes potential changes to some test code - Excludes potential changes to some external libs --- .../debug/debug-pal/unix/twowaypipe.cpp | 5 +- .../nativeaot/Runtime/unix/PalUnix.cpp | 13 ++++- .../pal/src/exception/machexception.cpp | 12 ++++- src/coreclr/pal/src/exception/signal.cpp | 49 +++++++++++++++++-- src/coreclr/pal/src/file/file.cpp | 2 +- src/coreclr/pal/src/map/map.cpp | 47 +++++++----------- src/coreclr/pal/src/misc/perfjitdump.cpp | 13 ++++- src/coreclr/pal/src/synchmgr/synchmanager.cpp | 5 +- src/mono/mono/component/debugger-agent.c | 2 +- src/mono/mono/mini/cfgdump.c | 22 ++++++++- src/mono/mono/profiler/log.c | 7 ++- src/native/eventpipe/ep-session.c | 29 +++++++++-- src/native/libs/System.Native/pal_console.c | 10 +++- 13 files changed, 166 insertions(+), 50 deletions(-) diff --git a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp index 9ca6509b48eda2..cb570fb3b00940 100644 --- a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp +++ b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp @@ -144,8 +144,11 @@ int TwoWayPipe::Write(const void *data, DWORD dataSize) int bytesWritten; int cb = dataSize; - while ((bytesWritten = (int)write(m_outboundPipe, data, cb)) > 0) + while (true) { + int bytesWritten; + while (-1 == (bytesWritten = (int)write(m_outboundPipe, data, cb)) && errno == EINTR); + if (bytesWritten <= 0) break; totalBytesWritten += bytesWritten; _ASSERTE(totalBytesWritten <= (int)dataSize); if (totalBytesWritten >= (int)dataSize) diff --git a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp index b6045f6f74d5ac..6db2ca64b8f09c 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp @@ -846,7 +846,18 @@ void PalPrintFatalError(const char* message) // message, so there is not much that can be done here. // write() has __attribute__((warn_unused_result)) in glibc, for which gcc 11+ issue `-Wunused-result` even with `(void)write(..)`, // so we use additional NOT(!) operator to force unused-result suppression. - (void)!write(STDERR_FILENO, message, strlen(message)); + size_t toWrite = strlen(message); + while (toWrite > 0) + { + ssize_t result = write(STDERR_FILENO, message, toWrite); + if (result < 0) + { + if (errno != EINTR) break; + else result = 0; + } + message += result; + toWrite -= result; + } } char* PalCopyTCharAsChar(const TCHAR* toCopy) diff --git a/src/coreclr/pal/src/exception/machexception.cpp b/src/coreclr/pal/src/exception/machexception.cpp index f52519959a8736..cc9761bbc51ed5 100644 --- a/src/coreclr/pal/src/exception/machexception.cpp +++ b/src/coreclr/pal/src/exception/machexception.cpp @@ -857,7 +857,17 @@ HijackFaultingThread( if ((stackOverflowHandlerStack == MAP_FAILED) || mprotect((void*)stackOverflowHandlerStack, GetVirtualPageSize(), PROT_NONE) != 0) { // We are out of memory or we've failed to protect the guard page, so resort to just printing a stack overflow message and abort - write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); + const char *message = StackOverflowMessage; + size_t messageSize = sizeof(StackOverflowMessage) - 1; + ssize_t writeResult; + while (true) + { + while (-1 == (writeResult = write(STDERR_FILENO, message, messageSize)) && errno == EINTR); + if (writeResult <= 0 || (ssize_t)messageSize < writeResult) break; + messageSize -= (size_t)writeResult; + message += writeResult; + if (messageSize == 0) break; + } abort(); } diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index 444bad7e5c072c..5b1e9ffcea01bb 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -652,9 +652,22 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context) if (GetCurrentPalThread()) { #if defined(TARGET_TVOS) - (void)!write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); + const char *message = StackOverflowMessage; + size_t messageSize = sizeof(StackOverflowMessage) - 1; + ssize_t writeResult; + while (true) + { + while (-1 == (writeResult = write(STDERR_FILENO, message, messageSize)) && errno == EINTR); + if (writeResult <= 0 || (ssize_t)messageSize < writeResult) break; + messageSize -= (size_t)writeResult; + message += writeResult; + if (messageSize == 0) break; + } PROCAbort(SIGSEGV, siginfo); #else // TARGET_TVOS + const char *message; + size_t messageSize; + ssize_t writeResult; size_t handlerStackTop = __sync_val_compare_and_swap((size_t*)&g_stackOverflowHandlerStack, (size_t)g_stackOverflowHandlerStack, 0); if (handlerStackTop == 0) { @@ -665,7 +678,16 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context) // Temporary check to debug issue https://github.com/dotnet/runtime/issues/110173 if (stackOverflowThreadId == THREADSilentGetCurrentThreadId()) { - (void)!write(STDERR_FILENO, StackOverflowOnTheSameThreadMessage, sizeof(StackOverflowOnTheSameThreadMessage) - 1); + message = StackOverflowOnTheSameThreadMessage; + messageSize = sizeof(StackOverflowOnTheSameThreadMessage) - 1; + while (true) + { + while (-1 == (writeResult = write(STDERR_FILENO, message, messageSize)) && errno == EINTR); + if (writeResult <= 0 || (ssize_t)messageSize < writeResult) break; + messageSize -= (size_t)writeResult; + message += writeResult; + if (messageSize == 0) break; + } } while (true) @@ -682,12 +704,31 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context) { PROCAbort(SIGSEGV, siginfo); } - (void)!write(STDERR_FILENO, StackOverflowHandlerReturnedMessage, sizeof(StackOverflowHandlerReturnedMessage) - 1); + message = StackOverflowHandlerReturnedMessage; + messageSize = sizeof(StackOverflowHandlerReturnedMessage) - 1; + while (true) + { + while (-1 == (writeResult = write(STDERR_FILENO, message, messageSize)) && errno == EINTR); + if (writeResult <= 0 || (ssize_t)messageSize < writeResult) break; + messageSize -= (size_t)writeResult; + message += writeResult; + if (messageSize == 0) break; + } #endif // TARGET_TVOS } else { - (void)!write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1); + const char *message = StackOverflowMessage; + size_t messageSize = sizeof(StackOverflowMessage) - 1; + ssize_t writeResult; + while (true) + { + while (-1 == (writeResult = write(STDERR_FILENO, message, messageSize)) && errno == EINTR); + if (writeResult <= 0 || (ssize_t)messageSize < writeResult) break; + messageSize -= (size_t)writeResult; + message += writeResult; + if (messageSize == 0) break; + } } // The current executable (shared library) doesn't have hardware exception handler installed or opted to not to diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 58d82dbaad3683..9382efd0055645 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -1125,7 +1125,7 @@ CorUnix::InternalWriteFile( } #endif - res = write( ifd, lpBuffer, nNumberOfBytesToWrite ); + while (-1 == (res = write( ifd, lpBuffer, nNumberOfBytesToWrite )) && errno == EINTR); TRACE("write() returns %d\n", res); if ( res >= 0 ) diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 8078b2e2c49912..af5fd220b528a8 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -1525,35 +1525,12 @@ static PAL_ERROR MAPGrowLocalFile( INT UnixFD, off_t NewSize ) } memset( buf, 0, BUFFER_SIZE ); - if (NewSize - OrigSize - BUFFER_SIZE >= 0 && BUFFER_SIZE > 0) + size_t toWrite = NewSize - (UINT)OrigSize; + while (toWrite > 0) { - for ( x = 0; x < NewSize - OrigSize - BUFFER_SIZE; x += BUFFER_SIZE ) - { - if ( write( UnixFD, (LPVOID)buf, BUFFER_SIZE ) == -1 ) - { - ERROR( "Unable to grow the file. Reason=%s\n", strerror( errno ) ); - if((errno == ENOSPC) || (errno == EDQUOT)) - { - palError = ERROR_DISK_FULL; - } - else - { - palError = ERROR_INTERNAL_ERROR; - } - goto done; - } - } - } - else - { - //This will be an infinite loop because it did not pass the check. - palError = ERROR_INTERNAL_ERROR; - goto done; - } - /* Catch any left overs. */ - if ( x != NewSize ) - { - if ( write( UnixFD, (LPVOID)buf, NewSize - OrigSize - x) == -1 ) + ssize_t writeResult; + while (-1 == (writeResult = write( UnixFD, (LPVOID)buf, std::min(toWrite, BUFFER_SIZE) )) && errno == EINTR); + if (writeResult == -1) { ERROR( "Unable to grow the file. Reason=%s\n", strerror( errno ) ); if((errno == ENOSPC) || (errno == EDQUOT)) @@ -1566,6 +1543,20 @@ static PAL_ERROR MAPGrowLocalFile( INT UnixFD, off_t NewSize ) } goto done; } + else if (writeResult == 0) + { + break; + } + else + { + toWrite -= (size_t)writeResult; + } + } + if (toWrite > 0) + { + palError = ERROR_INTERNAL_ERROR; + ERROR( "Unable to grow the file. Reason=%s\n", "write returned 0 earlier than expected." ); + goto done; } /* restore the file pointer position */ diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 9a851125208299..b2e50393b9e556 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -218,9 +218,18 @@ struct PerfJitDumpState fd = result; - result = write(fd, &header, sizeof(FileHeader)); + char* message = (char*)&header; + size_t messageSize = sizeof(FileHeader); + while (messageSize > 0) + { + while (-1 == (result = write(fd, message, messageSize)) && errno == EINTR); + if (result == -1) break; + messageSize -= result; + message += result; + if (messageSize == 0) break; + } - if (result == -1) + if (result == -1 || messageSize != 0) return FatalError(); while (-1 == (result = fsync(fd)) && errno == EINTR); diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index c459fdd18f9e53..1014f7440ee691 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -2165,9 +2165,10 @@ namespace CorUnix { sszWritten = write(m_iProcessPipeWrite, &byCmd, sizeof(BYTE)); } while (-1 == sszWritten && - EAGAIN == errno && + ((EAGAIN == errno && ++iRetryCount < MaxConsecutiveEagains && - 0 == sched_yield()); + 0 == sched_yield()) || + EINTR == errno)); if (sszWritten != sizeof(BYTE)) { diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index 342f82b550adb7..0ff97dc4b70468 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -7067,7 +7067,7 @@ valid_memory_address (gpointer addr, gint size) if(file_check_valid_memory < 0) { return TRUE; } - write (file_check_valid_memory, (gpointer)addr, 1); + while (-1 == write (file_check_valid_memory, (gpointer)addr, 1) && errno == EINTR); if (errno == EFAULT) { ret = FALSE; } diff --git a/src/mono/mono/mini/cfgdump.c b/src/mono/mono/mini/cfgdump.c index 7d6142e21ea158..3b6646362090ba 100644 --- a/src/mono/mono/mini/cfgdump.c +++ b/src/mono/mono/mini/cfgdump.c @@ -81,14 +81,32 @@ write_short (MonoCompile *cfg, short s) { short swap = htons (s); int ret; - while ((ret = write (cfg->gdump_ctx->fd, &swap, 2)) < 0 && errno == EINTR); + char* message = (char*)&swap; + size_t messageSize = 2; + do + { + while ((ret = write (cfg->gdump_ctx->fd, message, messageSize)) < 0 && errno == EINTR); + if (ret <= 0) break; + message += ret; + messageSize -= ret; + } + while (messageSize > 0); } static void write_int (MonoCompile *cfg, int v) { int swap = htonl (v), ret; - while ((ret = write (cfg->gdump_ctx->fd, &swap, 4)) < 0 && errno == EINTR); + char* message = (char*)&swap; + size_t messageSize = 4; + do + { + while ((ret = write (cfg->gdump_ctx->fd, message, messageSize)) < 0 && errno == EINTR); + if (ret <= 0) break; + message += ret; + messageSize -= ret; + } + while (messageSize > 0); } static void diff --git a/src/mono/mono/profiler/log.c b/src/mono/mono/profiler/log.c index 8d643dadaebe50..a7c7c4217eab75 100644 --- a/src/mono/mono/profiler/log.c +++ b/src/mono/mono/profiler/log.c @@ -11,6 +11,7 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ +#include #include #include #include @@ -2498,7 +2499,9 @@ static void signal_helper_thread (char c) { #ifdef HAVE_COMMAND_PIPES - if (write (log_profiler.pipes [1], &c, 1) != 1) { + ssize_t result; + while (-1 == (result = write (log_profiler.pipes [1], &c, 1)) && errno == EINTR); + if (result != 1) { mono_profiler_printf_err ("Could not write to log profiler pipe: %s", g_strerror (errno)); exit (1); } @@ -3835,4 +3838,4 @@ proflog_trigger_heapshot (void) while (handle_writer_queue_entry ()); while (handle_dumper_queue_entry ()); -} \ No newline at end of file +} diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index ac9cf1d7e36320..41d7872c8e5aef 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -228,7 +228,7 @@ session_user_events_tracepoints_init ( EP_ASSERT (session_provider != NULL); ep_raise_error_if_nok (ep_session_provider_register_tracepoints (session_provider, session->user_events_data_fd)); } DN_LIST_FOREACH_END; - + result = true; ep_on_exit: @@ -366,7 +366,7 @@ ep_session_remove_dangling_session_states (EventPipeSession *session) EventPipeThreadSessionState *session_state = ep_thread_get_session_state(thread, session); if (session_state) { // If a buffer tries to write event(s) but never gets a buffer because the maximum total buffer size - // has been exceeded, we can leak the EventPipeThreadSessionState* and crash later trying to access + // has been exceeded, we can leak the EventPipeThreadSessionState* and crash later trying to access // the session from the thread session state. Whenever we terminate a session we check to make sure // we haven't leaked any thread session states. ep_thread_delete_session_state(thread, session); @@ -685,7 +685,7 @@ construct_extension_activity_ids_buffer ( memcpy (extension + offset, activity_id, EP_ACTIVITY_ID_SIZE); offset += EP_ACTIVITY_ID_SIZE; } - + EP_ASSERT ((size_t)(offset + 1 + EP_ACTIVITY_ID_SIZE) <= extension_size); if (!related_activity_id_is_empty) { extension[offset] = 0x03; @@ -837,7 +837,28 @@ session_tracepoint_write_event ( payload_rel_loc = ep_event_payload_total_size << 16 | (extension_len & 0xFFFF); ssize_t bytes_written; - while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, io_index) < 0) && errno == EINTR); + struct iovec *iov = io; + int iovcnt = io_index; + while (iovcnt > 0) + { + while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)iov, iovcnt) < 0) && errno == EINTR); + if (bytes_written <= 0) break; + while (iovcnt > 0 && bytes_written > 0) + { + if (iov->iov_len >= bytes_written) + { + bytes_written -= iov->iov_len; + iovcnt--; + iov++; + } + else + { + iov->iov_len -= bytes_written; + iov->iov_base += bytes_written; + break; + } + } + } if (io != static_io) free (io); diff --git a/src/native/libs/System.Native/pal_console.c b/src/native/libs/System.Native/pal_console.c index 6716d8cb77da87..36211bae72ca98 100644 --- a/src/native/libs/System.Native/pal_console.c +++ b/src/native/libs/System.Native/pal_console.c @@ -56,7 +56,15 @@ static void WriteKeypadXmit(void) if (g_keypadXmit != NULL) { ssize_t ret; - while (CheckInterrupted(ret = write(g_keypadXmitFd, g_keypadXmit, (size_t)(sizeof(char) * strlen(g_keypadXmit))))); + char* message = g_keypadXmit; + size_t messageSize = (size_t)(sizeof(char) * strlen(g_keypadXmit)); + while (messageSize > 0) + { + while (CheckInterrupted(ret = write(g_keypadXmitFd, message, messageSize))); + if (ret <= 0) break; + messageSize -= ret; + message += ret; + } assert(ret >= 0 || (errno == EBADF && g_keypadXmitFd == 0)); // failure to change the mode should not prevent app from continuing } } From 89876342868a6dca3acc15ba7a09acaf930b16a0 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Wed, 30 Jul 2025 11:27:18 +1000 Subject: [PATCH 33/50] Fix handling of `closedir` giving `EINTR` --- src/coreclr/tools/superpmi/mcs/verbmerge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp index b1986fd8c0cf7a..c723e4ce12fb51 100644 --- a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp +++ b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp @@ -399,7 +399,7 @@ int verbMerge::FilterDirectory(LPCWSTR dir, return -1; } #else // TARGET_WINDOWS - if (pDir != nullptr && (closedir(pDir) != 0)) + if (pDir != nullptr && (closedir(pDir) != 0 && errno != EINTR)) { LogError("Failed to close directory. errno=%d", errno); delete[] retArray; From e99a73959065aa6239e270374a777e96e652dec2 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 3 Oct 2025 08:30:32 +1000 Subject: [PATCH 34/50] Ensure we handle EINTR & partial operations more consistently for pread --- .../debug/createdump/crashinfounix.cpp | 2 +- src/coreclr/pal/src/map/map.cpp | 91 ++++++++++++++++--- 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfounix.cpp b/src/coreclr/debug/createdump/crashinfounix.cpp index 1d7226a2c7affa..d417db54b356e2 100644 --- a/src/coreclr/debug/createdump/crashinfounix.cpp +++ b/src/coreclr/debug/createdump/crashinfounix.cpp @@ -543,7 +543,7 @@ CrashInfo::ReadProcessMemory(uint64_t address, void* buffer, size_t size, size_t // performance optimization. m_canUseProcVmReadSyscall = false; assert(m_fdMem != -1); - *read = pread(m_fdMem, buffer, size, (off_t)address); + while (-1 == (ssize_t)(*read = pread(m_fdMem, buffer, size, (off_t)address)) && errno == EINTR); } if (*read == (size_t)-1) diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index af5fd220b528a8..d06418747e6756 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -1968,9 +1968,36 @@ MAPmmapAndRecord( // Set the requested mapping with forced PROT_WRITE to ensure data from the file can be read there, // read the data in and finally remove the forced PROT_WRITE. On Intel we can still switch the // protection later with mprotect. - if ((mprotect(pvBaseAddress, len + adjust, PROT_WRITE) == -1) || - (pread(fd, pvBaseAddress, len + adjust, offset - adjust) == -1) || - (mprotect(pvBaseAddress, len + adjust, prot) == -1)) + bool failCondition = mprotect(pvBaseAddress, len + adjust, PROT_WRITE) == -1; + if (!failCondition) + { + unsigned char* buf = pvBaseAddress; + size_t nbyte = len + adjust; + size_t offset2 = offset - adjust; + while (nbyte > 0) + { + ssize_t result; + while (-1 == result = pread(fd, buf, nbyte, offset2) && errno == EINTR); + if (result == -1) + { + failCondition = true; + break; + } + buf += result; + nbyte -= result; + offset2 += result; + if (result == 0) + { + if (nbyte > 0) + { + failCondition = true; + errno = EIO; // set to a generic IO error, to indicate that we couldn't read the whole requested region + } + break; + } + } + } + if (failCondition || (mprotect(pvBaseAddress, len + adjust, prot) == -1)) { palError = FILEGetLastErrorFromErrno(); } @@ -2080,16 +2107,54 @@ void * MAPMapPEFile(HANDLE hFile, off_t offset) //Step 1: Read the PE headers and reserve enough space for the whole image somewhere. IMAGE_DOS_HEADER dosHeader; IMAGE_NT_HEADERS ntHeader; - if (sizeof(dosHeader) != pread(fd, &dosHeader, sizeof(dosHeader), offset)) - { - palError = FILEGetLastErrorFromErrno(); - ERROR_(LOADER)( "reading dos header failed\n" ); - goto done; - } - if (sizeof(ntHeader) != pread(fd, &ntHeader, sizeof(ntHeader), offset + dosHeader.e_lfanew)) - { - palError = FILEGetLastErrorFromErrno(); - goto done; + unsigned char* preadBuf = &dosHeader; + size_t nbyte = sizeof(dosHeader); + size_t preadOffset = offset; + while (nbyte > 0) + { + ssize_t result; + while (-1 == result = pread(fd, preadBuf, nbyte, preadOffset) && errno == EINTR); + if (result == 0) + { + if (nbyte > 0) + { + errno = EIO; // set to a generic IO error, to indicate that we couldn't read the whole requested region + result = -1; + } + } + if (result == -1) + { + palError = FILEGetLastErrorFromErrno(); + ERROR_(LOADER)( "reading dos header failed\n" ); + goto done; + } + preadBuf += result; + nbyte -= result; + preadOffset += result; + } + unsigned char* preadBuf = &ntHeader; + size_t nbyte = sizeof(ntHeader); + size_t preadOffset = offset + dosHeader.e_lfanew; + while (nbyte > 0) + { + ssize_t result; + while (-1 == result = pread(fd, preadBuf, nbyte, preadOffset) && errno == EINTR); + if (result == 0) + { + if (nbyte > 0) + { + errno = EIO; // set to a generic IO error, to indicate that we couldn't read the whole requested region + result = -1; + } + } + if (result == -1) + { + palError = FILEGetLastErrorFromErrno(); + goto done; + } + preadBuf += result; + nbyte -= result; + preadOffset += result; } if ((VAL16(IMAGE_DOS_SIGNATURE) != VAL16(dosHeader.e_magic)) From ae267571fffce738ae11e61186b4a0784200c4a3 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 3 Oct 2025 09:56:20 +1000 Subject: [PATCH 35/50] Ensure we handle EINTR & partial operations more consistently for read - Excludes some potential changes to mono profiler, SystemNative_ReadEvents (seems broken maybe?) --- src/coreclr/debug/createdump/crashinfo.cpp | 21 +++++++++--- .../debug/createdump/crashinfounix.cpp | 18 ++++++++++- .../debug/debug-pal/unix/twowaypipe.cpp | 4 ++- .../nativeaot/Runtime/unix/PalCreateDump.cpp | 6 ++-- src/coreclr/pal/src/synchmgr/synchmanager.cpp | 2 +- src/coreclr/pal/src/thread/process.cpp | 4 ++- src/coreclr/pal/src/thread/thread.cpp | 12 +++++-- src/mono/mono/utils/dlmalloc.c | 13 ++++++-- src/mono/mono/utils/mono-filemap.c | 10 ++++-- src/mono/mono/utils/mono-proclib.c | 14 ++++++-- src/native/minipal/debugger.c | 32 +++++++++++++++---- 11 files changed, 108 insertions(+), 28 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index b0863cceb51d0d..fb074825c51b8e 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -823,12 +823,23 @@ CrashInfo::PageMappedToPhysicalMemory(uint64_t start) return true; } uint64_t value; - size_t readResult = read(m_fdPagemap, (void*)&value, sizeof(value)); - if (readResult == (size_t) -1) + size_t readSoFar = 0; + while (readSoFar < sizeof(value)) { - int readErrno = errno; - TRACE("Reading of pagemap file FAILED, addr: %" PRIA PRIx ", pagemap offset: %" PRIA PRIx ", size: %zu, ERRNO %d: %s\n", start, pagemapOffset, sizeof(value), readErrno, strerror(readErrno)); - return true; + size_t readResult; + while (-1 == (readResult = read(m_fdPagemap, (unsigned char*)&value + readSoFar, sizeof(value) - readSoFar) && errno == EINTR)); + if (readResult == (size_t) -1) + { + int readErrno = errno; + TRACE("Reading of pagemap file FAILED, addr: %" PRIA PRIx ", pagemap offset: %" PRIA PRIx ", size: %zu, ERRNO %d: %s\n", start, pagemapOffset, sizeof(value), readErrno, strerror(readErrno)); + return true; + } + if (readResult == 0) + { + TRACE("Reading of pagemap file FAILED, addr: %" PRIA PRIx ", pagemap offset: %" PRIA PRIx ", size: %zu, Read Was Incomplete\n", start, pagemapOffset, sizeof(value)); + return true; + } + readSoFar += readResult; } bool is_page_present = (value & ((uint64_t)1 << 63)) != 0; diff --git a/src/coreclr/debug/createdump/crashinfounix.cpp b/src/coreclr/debug/createdump/crashinfounix.cpp index d417db54b356e2..d27a38d1244a47 100644 --- a/src/coreclr/debug/createdump/crashinfounix.cpp +++ b/src/coreclr/debug/createdump/crashinfounix.cpp @@ -186,8 +186,24 @@ CrashInfo::GetAuxvEntries() bool result = false; elf_aux_entry auxvEntry; - while (read(fd, &auxvEntry, sizeof(elf_aux_entry)) == sizeof(elf_aux_entry)) + while (true) { + size_t readSoFar = 0; + while (readSoFar < sizeof(elf_aux_entry)) + { + size_t readResult; + while (-1 == (readResult = read(fd, (unsigned char*)&auxvEntry + readSoFar, sizeof(elf_aux_entry) - readSoFar) && errno == EINTR)); + if (readResult == (size_t) -1) + { + break; + } + if (readResult == 0) + { + break; + } + readSoFar += readResult; + } + if (readSoFar != sizeof(elf_aux_entry)) break; m_auxvEntries.push_back(auxvEntry); if (auxvEntry.a_type == AT_NULL) { diff --git a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp index cb570fb3b00940..b2cd010c2d4929 100644 --- a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp +++ b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp @@ -117,8 +117,10 @@ int TwoWayPipe::Read(void *buffer, DWORD bufferSize) int bytesRead; int cb = bufferSize; - while ((bytesRead = (int)read(m_inboundPipe, buffer, cb)) > 0) + while (true) { + while (-1 == (bytesRead = (int)read(m_inboundPipe, buffer, cb)) && errno == EINTR); + if (bytesRead <= 0) break; totalBytesRead += bytesRead; _ASSERTE(totalBytesRead <= (int)bufferSize); if (totalBytesRead >= (int)bufferSize) diff --git a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp index eec52317ebcdfd..41ee1d4cc17c4a 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp @@ -55,7 +55,7 @@ // Crash dump generating program arguments. MAX_ARGV_ENTRIES is the max number // of entries if every createdump option/argument is passed. -#define MAX_ARGV_ENTRIES 32 +#define MAX_ARGV_ENTRIES 32 const char* g_argvCreateDump[MAX_ARGV_ENTRIES] = { nullptr }; char* g_szCreateDumpPath = nullptr; char* g_ppidarg = nullptr; @@ -280,8 +280,10 @@ CreateCrashDump( // Read createdump's stderr int bytesRead = 0; int count = 0; - while ((count = read(parent_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0) + while (true) { + while (-1 == (count = read(parent_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) && errno == EINTR); + if (count <= 0) break; bytesRead += count; } errorMessageBuffer[bytesRead] = 0; diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index 1014f7440ee691..90fabfdece4f07 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -1937,7 +1937,7 @@ namespace CorUnix } #endif // HAVE_KQUEUE - iRet = read(m_iProcessPipeRead, pPos, iBytes - iBytesRead); + while (-1 == (iRet = read(m_iProcessPipeRead, pPos, iBytes - iBytesRead)) && errno == EINTR); if (0 == iRet) { diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 70296c85aa7270..c07bc680bbc10d 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -2297,8 +2297,10 @@ PROCCreateCrashDump( // Read createdump's stderr int bytesRead = 0; int count = 0; - while ((count = read(parent_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0) + while (true) { + while (-1 == (count = read(parent_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) && errno == EINTR); + if (count <= 0) break; bytesRead += count; } errorMessageBuffer[bytesRead] = 0; diff --git a/src/coreclr/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index fc58d9ded6c58e..b195464949d109 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -1390,11 +1390,17 @@ CorUnix::GetThreadTimesInternal( } lwpstatus_t status; - do + size_t readSoFar = 0; + while (readSoFar < sizeof(status)) { - readResult = read(fd, &status, sizeof(status)); + do + { + readResult = read(fd, (unsigned char*)&status + readSoFar, sizeof(status) - readSoFar); + } + while ((readResult == -1) && (errno == EINTR)); + if (readResult <= 0) break; + readSoFar += readResult; } - while ((readResult == -1) && (errno == EINTR)); close(fd); diff --git a/src/mono/mono/utils/dlmalloc.c b/src/mono/mono/utils/dlmalloc.c index c993521b903b91..4f06f0c056c3d5 100644 --- a/src/mono/mono/utils/dlmalloc.c +++ b/src/mono/mono/utils/dlmalloc.c @@ -2461,10 +2461,17 @@ static int init_mparams(void) { unsigned char buf[sizeof(size_t)]; /* Try to use /dev/urandom, else fall back on using time */ while (-1 == (fd = open("/dev/urandom", O_RDONLY)) && errno == EINTR); - if (fd >= 0 && - read(fd, buf, sizeof(buf)) == sizeof(buf)) { + size_t readSoFar = 0; + while (fd >= 0 && readSoFar < sizeof(buf)) + { + ssize_t numRead; + while (-1 == (numRead = read(fd, buf + numRead, sizeof(buf) - numRead)) && errno == EINTR); + if (numRead <= 0) break; + readSoFar += numRead; + } + if (fd >= 0) close(fd); + if (readSoFar == sizeof(buf)) { s = *((size_t *) buf); - close(fd); } else #endif /* USE_DEV_RANDOM */ diff --git a/src/mono/mono/utils/mono-filemap.c b/src/mono/mono/utils/mono-filemap.c index a2a7e53037e7cb..baf15bd96c9d69 100644 --- a/src/mono/mono/utils/mono-filemap.c +++ b/src/mono/mono/utils/mono-filemap.c @@ -105,8 +105,14 @@ mono_file_map_fileio (size_t length, int flags, int fd, guint64 offset, void **r (*release_fn) (ptr); return NULL; } - bytes_read = read (fd, ptr, length); - if (bytes_read != length) + size_t readSoFar = 0; + while (readSoFar < length) + { + while (-1 == (bytes_read = read (fd, ptr + readSoFar, length - readSoFar)) && errno == EINTR); + if (bytes_read <= 0) break; + readSoFar += bytes_read; + } + if (readSoFar != length) return NULL; while (-1 == lseek (fd, cur_offset, SEEK_SET) && errno == EINTR); *ret_handle = NULL; diff --git a/src/mono/mono/utils/mono-proclib.c b/src/mono/mono/utils/mono-proclib.c index a24932d7f936d1..39b98de2de1203 100644 --- a/src/mono/mono/utils/mono-proclib.c +++ b/src/mono/mono/utils/mono-proclib.c @@ -90,10 +90,20 @@ mono_cpu_count (void) * 1 core, n being the number of CPU cores in the system. Otherwise * the value is simply 0 */ - if (present != -1 && read (present, (char*)buffer, sizeof (buffer)) > 3) - count = strtol (((char*)buffer) + 2, NULL, 10); if (present != -1) + { + size_t readSoFar = 0; + while (readSoFar < sizeof (buffer)) + { + ssize_t numRead; + while (-1 == (numRead = read (present, (char*)buffer + readSoFar, sizeof (buffer) - readSoFar)) && errno == EINTR); + if (numRead <= 0) break; + readSoFar += numRead; + } + if (readSoFar > 3) + count = strtol (((char*)buffer) + 2, NULL, 10); close (present); + } if (count > 0) return count + 1; #endif diff --git a/src/native/minipal/debugger.c b/src/native/minipal/debugger.c index 22c720298ec103..5aea3763d72f93 100644 --- a/src/native/minipal/debugger.c +++ b/src/native/minipal/debugger.c @@ -70,13 +70,25 @@ bool minipal_is_native_debugger_present(void) { return false; } - ssize_t num_read = read(status_fd, buf, sizeof(buf) - 1); - if (num_read > 0) + ssize_t readSoFar = 0; + while (readSoFar < sizeof(buf) - 1) + { + ssize_t num_read; + while (-1 == (num_read = read(status_fd, buf + readSoFar, sizeof(buf) - 1 - readSoFar)) && errno == EINTR); + if (num_read == 0) break; + if (num_read < 0) + { + readSoFar = -1; + break; + } + readSoFar += num_read; + } + if (readSoFar > 0) { static const char TracerPid[] = "TracerPid:"; char *tracer_pid; - buf[num_read] = '\0'; + buf[readSoFar] = '\0'; tracer_pid = strstr(buf, TracerPid); if (tracer_pid) { @@ -133,11 +145,17 @@ bool minipal_is_native_debugger_present(void) } pstatus_t status; - ssize_t readResult; - do + size_t readSoFar = 0; + while (readSoFar < sizeof(status)) { - readResult = read(fd, &status, sizeof(status)); - } while (readResult == -1 && errno == EINTR); + ssize_t readResult; + do + { + readResult = read(fd, &status + readSoFar, sizeof(status) - readSoFar); + } while (readResult == -1 && errno == EINTR); + if (readResult <= 0) break; + readSoFar += readResult; + } close(fd); return status.pr_flttrace.word[0] != 0; From 67523346b3587134e435f09e0e9159a0a915c1ac Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 3 Oct 2025 10:17:20 +1000 Subject: [PATCH 36/50] Fix first set of build failures --- src/coreclr/pal/src/file/file.cpp | 2 +- src/native/minipal/debugger.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index ee9eba6302f2b8..507536cf4599d5 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -727,7 +727,7 @@ CorUnix::InternalCreateFile( } if (bFileCreated) { - int ulink_result; + int unlink_result; while (-1 == (unlink_result = unlink(lpUnixPath)) && errno == EINTR); if (-1 == unlink_result) { diff --git a/src/native/minipal/debugger.c b/src/native/minipal/debugger.c index 9d9ce16a136c9a..4fc2e6027d6dad 100644 --- a/src/native/minipal/debugger.c +++ b/src/native/minipal/debugger.c @@ -20,6 +20,7 @@ #define MINIPAL_DEBUGGER_PRESENT_CHECK #elif defined(__linux__) #include +#include #define MINIPAL_DEBUGGER_PRESENT_CHECK #elif defined(__APPLE__) || defined(__FreeBSD__) #include From 23b62756f7f806eb297b87d05e58b0faa0193766 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 3 Oct 2025 10:25:05 +1000 Subject: [PATCH 37/50] Fix build failures --- src/coreclr/pal/src/file/file.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 507536cf4599d5..31c73dbb1842bd 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -2193,7 +2193,6 @@ CorUnix::InternalCreatePipe( palError = ERROR_INTERNAL_ERROR; goto InternalCreatePipeExit; } - int fcntl_result; while (-1 == (fcntl_result = fcntl(readWritePipeDes[1],F_SETFD,FD_CLOEXEC)) && errno == EINTR); if(-1 == fcntl_result) { From 70051f48d3b06f5262009e7de4f58326ff15a900 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 3 Oct 2025 10:40:53 +1000 Subject: [PATCH 38/50] Fix build failures --- src/native/libs/System.Native/pal_console.c | 4 ++-- .../libs/System.Security.Cryptography.Native/pal_x509.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/native/libs/System.Native/pal_console.c b/src/native/libs/System.Native/pal_console.c index 36211bae72ca98..f03fb1b2adcc10 100644 --- a/src/native/libs/System.Native/pal_console.c +++ b/src/native/libs/System.Native/pal_console.c @@ -55,14 +55,14 @@ static void WriteKeypadXmit(void) // write it out to the terminal to enter the mode. if (g_keypadXmit != NULL) { - ssize_t ret; + ssize_t ret = 0; char* message = g_keypadXmit; size_t messageSize = (size_t)(sizeof(char) * strlen(g_keypadXmit)); while (messageSize > 0) { while (CheckInterrupted(ret = write(g_keypadXmitFd, message, messageSize))); if (ret <= 0) break; - messageSize -= ret; + messageSize -= (size_t)ret; message += ret; } assert(ret >= 0 || (errno == EBADF && g_keypadXmitFd == 0)); // failure to change the mode should not prevent app from continuing diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c index 73ddebb4f7d596..d1ec0baff066c9 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c @@ -5,7 +5,7 @@ #include "../Common/pal_safecrt.h" #include -#include +#include #include #include #include From ffc73d2a0dde855166ea2e733ca9aeb8d26a7424 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 3 Oct 2025 10:48:46 +1000 Subject: [PATCH 39/50] Fix build failures --- src/coreclr/pal/src/file/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/pal/src/file/file.cpp b/src/coreclr/pal/src/file/file.cpp index 31c73dbb1842bd..3fb7a987f29a5e 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -1124,7 +1124,7 @@ CorUnix::InternalWriteFile( } #endif - while (-1 == (res = write( ifd, lpBuffer, nNumberOfBytesToWrite )) && errno == EINTR); + while (-1 == (res = write( ifd, lpBuffer, nNumberOfBytesToWrite )) && errno == EINTR) { } TRACE("write() returns %d\n", res); if ( res >= 0 ) From 67adb47f3e5d6fb16994b39710c5e3bb7ae87ac6 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Fri, 3 Oct 2025 10:58:10 +1000 Subject: [PATCH 40/50] Fix build failures --- src/mono/mono/utils/mono-filemap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/utils/mono-filemap.c b/src/mono/mono/utils/mono-filemap.c index baf15bd96c9d69..639b09101934c4 100644 --- a/src/mono/mono/utils/mono-filemap.c +++ b/src/mono/mono/utils/mono-filemap.c @@ -108,7 +108,7 @@ mono_file_map_fileio (size_t length, int flags, int fd, guint64 offset, void **r size_t readSoFar = 0; while (readSoFar < length) { - while (-1 == (bytes_read = read (fd, ptr + readSoFar, length - readSoFar)) && errno == EINTR); + while (-1 == (bytes_read = read (fd, (unsigned char*)ptr + readSoFar, length - readSoFar)) && errno == EINTR); if (bytes_read <= 0) break; readSoFar += bytes_read; } From 8f0530e196ba16d7de6a1a5789f5f2f9965e4b3b Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 7 Oct 2025 18:35:34 +1100 Subject: [PATCH 41/50] Fix build errors --- src/coreclr/pal/src/map/map.cpp | 26 +++++++++++-------- src/coreclr/pal/src/misc/perfjitdump.cpp | 6 +++-- .../pal/src/sharedmemory/sharedmemory.cpp | 4 +-- src/coreclr/pal/src/thread/threadsusp.cpp | 4 +-- src/mono/mono/component/debugger-poll.c | 1 + src/native/eventpipe/ep-session.c | 2 +- 6 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index d06418747e6756..343fe7f7b9ecd6 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -35,6 +35,7 @@ Module Name: #include #include #include +#include #include "rt/ntimage.h" #include @@ -1507,9 +1508,9 @@ static PAL_ERROR MAPGrowLocalFile( INT UnixFD, off_t NewSize ) TRACE( "Trying the less efficient way.\n" ); off_t lseek_result; - while (-1 == (lseek_result lseek( UnixFD, 0, SEEK_CUR )) && errno == EINTR); + while (-1 == (lseek_result = lseek( UnixFD, 0, SEEK_CUR )) && errno == EINTR); CurrentPosition = lseek_result; - while (-1 == (lseek_result lseek( UnixFD, 0, SEEK_END )) && errno == EINTR); + while (-1 == (lseek_result = lseek( UnixFD, 0, SEEK_END )) && errno == EINTR); OrigSize = lseek_result; if ( OrigSize == -1 ) { @@ -1529,7 +1530,7 @@ static PAL_ERROR MAPGrowLocalFile( INT UnixFD, off_t NewSize ) while (toWrite > 0) { ssize_t writeResult; - while (-1 == (writeResult = write( UnixFD, (LPVOID)buf, std::min(toWrite, BUFFER_SIZE) )) && errno == EINTR); + while (-1 == (writeResult = write( UnixFD, (LPVOID)buf, std::min(toWrite, (size_t)BUFFER_SIZE) )) && errno == EINTR); if (writeResult == -1) { ERROR( "Unable to grow the file. Reason=%s\n", strerror( errno ) ); @@ -2107,13 +2108,16 @@ void * MAPMapPEFile(HANDLE hFile, off_t offset) //Step 1: Read the PE headers and reserve enough space for the whole image somewhere. IMAGE_DOS_HEADER dosHeader; IMAGE_NT_HEADERS ntHeader; - unsigned char* preadBuf = &dosHeader; - size_t nbyte = sizeof(dosHeader); - size_t preadOffset = offset; + unsigned char *preadBuf; + preadBuf = (unsigned char*)&dosHeader; + size_t nbyte; + nbyte = sizeof(dosHeader); + size_t preadOffset; + preadOffset = offset; while (nbyte > 0) { ssize_t result; - while (-1 == result = pread(fd, preadBuf, nbyte, preadOffset) && errno == EINTR); + while (-1 == (result = pread(fd, preadBuf, nbyte, preadOffset)) && errno == EINTR); if (result == 0) { if (nbyte > 0) @@ -2132,13 +2136,13 @@ void * MAPMapPEFile(HANDLE hFile, off_t offset) nbyte -= result; preadOffset += result; } - unsigned char* preadBuf = &ntHeader; - size_t nbyte = sizeof(ntHeader); - size_t preadOffset = offset + dosHeader.e_lfanew; + preadBuf = (unsigned char*)&ntHeader; + nbyte = sizeof(ntHeader); + preadOffset = offset + dosHeader.e_lfanew; while (nbyte > 0) { ssize_t result; - while (-1 == result = pread(fd, preadBuf, nbyte, preadOffset) && errno == EINTR); + while (-1 == (result = pread(fd, preadBuf, nbyte, preadOffset)) && errno == EINTR); if (result == 0) { if (nbyte > 0) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index aea53af702c65c..b260f48d2ce948 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -219,8 +219,10 @@ struct PerfJitDumpState fd = result; - char* message = (char*)&header; - size_t messageSize = sizeof(FileHeader); + char* message; + message = (char*)&header; + size_t messageSize; + messageSize = sizeof(FileHeader); while (messageSize > 0) { while (-1 == (result = write(fd, message, messageSize)) && errno == EINTR); diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 228b0535cd4178..15e13884009d87 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -198,7 +198,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( if (isGlobalLockAcquired) { int operationResult; - while (-1 == (mkdir_result = mkdir(path, permissionsMask)) && errno == EINTR); + while (-1 == (operationResult = mkdir(path, permissionsMask)) && errno == EINTR); if (operationResult != 0) { if (errors != nullptr) @@ -1043,7 +1043,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( if (m_createdFile) { _ASSERTE(m_filePath != nullptr); - while (-1 == unlink(m_filePath) && errno == EINTR); + while (-1 == unlink(*m_filePath) && errno == EINTR); } if (m_sessionDirectoryPathCharCount != 0) diff --git a/src/coreclr/pal/src/thread/threadsusp.cpp b/src/coreclr/pal/src/thread/threadsusp.cpp index 1848c9257cb72b..bfa9e2f09647c2 100644 --- a/src/coreclr/pal/src/thread/threadsusp.cpp +++ b/src/coreclr/pal/src/thread/threadsusp.cpp @@ -77,9 +77,9 @@ CThreadSuspensionInfo::InternalSuspendNewThreadFromData( int pipeRv; while (-1 == (pipeRv = #if HAVE_PIPE2 - pipe2(pipe_descs, O_CLOEXEC); + pipe2(pipe_descs, O_CLOEXEC) #else - pipe(pipe_descs); + pipe(pipe_descs) #endif // HAVE_PIPE2 ) && errno == EINTR); if (pipeRv == -1) diff --git a/src/mono/mono/component/debugger-poll.c b/src/mono/mono/component/debugger-poll.c index 0e7f4ee96a43dc..6d32f900e27c28 100644 --- a/src/mono/mono/component/debugger-poll.c +++ b/src/mono/mono/component/debugger-poll.c @@ -44,6 +44,7 @@ mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout) { int result; while (-1 == (result = poll (ufds, nfds, timeout)) && errno == EINTR); + return result; } #else diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index d1406423807e13..bd15d4367c11bb 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -915,7 +915,7 @@ session_tracepoint_write_event ( else { iov->iov_len -= bytes_written; - iov->iov_base += bytes_written; + iov->iov_base = (unsigned char*)iov->iov_base + bytes_written; break; } } From 7a0a208f1ff19ff066de57002dd68533bb6445d9 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 7 Oct 2025 19:01:03 +1100 Subject: [PATCH 42/50] Fix build error --- src/coreclr/debug/debug-pal/unix/twowaypipe.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp index b2cd010c2d4929..bd1f718eea0ba9 100644 --- a/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp +++ b/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp @@ -148,7 +148,6 @@ int TwoWayPipe::Write(const void *data, DWORD dataSize) while (true) { - int bytesWritten; while (-1 == (bytesWritten = (int)write(m_outboundPipe, data, cb)) && errno == EINTR); if (bytesWritten <= 0) break; totalBytesWritten += bytesWritten; From 7185b991d8f997a09f562a9103dfbfcd6ae258cb Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 7 Oct 2025 19:18:54 +1100 Subject: [PATCH 43/50] Fix compiler error --- src/native/eventpipe/ep-session.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index c5f378dd04991b..8f286256fe435c 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -898,12 +898,14 @@ session_tracepoint_write_event ( payload_rel_loc = ep_event_payload_total_size << 16 | (extension_len & 0xFFFF); ssize_t bytes_written; + ssize_t bytes_written_total = 0; struct iovec *iov = io; int iovcnt = io_index; while (iovcnt > 0) { while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)iov, iovcnt) < 0) && errno == EINTR); if (bytes_written <= 0) break; + bytes_written_total += bytes_written; while (iovcnt > 0 && bytes_written > 0) { if (iov->iov_len >= bytes_written) @@ -921,6 +923,9 @@ session_tracepoint_write_event ( } } + if (should_write_metadata && (bytes_written == io_bytes_to_write)) + ep_event_update_metadata_written_mask (ep_event, session_mask, true); + if (io != static_io) free (io); From 3f850e77c376b28002ed67cda357d270be26520e Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 7 Oct 2025 19:19:22 +1100 Subject: [PATCH 44/50] typo --- src/native/eventpipe/ep-session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 8f286256fe435c..6255050b11a642 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -923,7 +923,7 @@ session_tracepoint_write_event ( } } - if (should_write_metadata && (bytes_written == io_bytes_to_write)) + if (should_write_metadata && (bytes_written_total == io_bytes_to_write)) ep_event_update_metadata_written_mask (ep_event, session_mask, true); if (io != static_io) From 701891261d816a5bf6471c84b90042b0bcab3166 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 7 Oct 2025 19:59:59 +1100 Subject: [PATCH 45/50] Fix build errors --- src/coreclr/pal/src/map/map.cpp | 4 ++-- src/coreclr/pal/src/synchmgr/synchmanager.cpp | 22 +++++++++---------- src/native/eventpipe/ds-ipc-pal-socket.c | 16 +++++++------- src/native/libs/System.Native/pal_ifaddrs.c | 2 +- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 343fe7f7b9ecd6..2ca72367fb2be3 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -1972,13 +1972,13 @@ MAPmmapAndRecord( bool failCondition = mprotect(pvBaseAddress, len + adjust, PROT_WRITE) == -1; if (!failCondition) { - unsigned char* buf = pvBaseAddress; + unsigned char *buf = (unsigned char*)pvBaseAddress; size_t nbyte = len + adjust; size_t offset2 = offset - adjust; while (nbyte > 0) { ssize_t result; - while (-1 == result = pread(fd, buf, nbyte, offset2) && errno == EINTR); + while (-1 == (result = pread(fd, buf, nbyte, offset2)) && errno == EINTR); if (result == -1) { failCondition = true; diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index 90fabfdece4f07..031cadc259290c 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -1850,7 +1850,7 @@ namespace CorUnix Poll.events = POLLIN; Poll.revents = 0; - while (-1 == (iRet = poll(&Poll, 1, iTimeout)) && errno == EINTR); + while (-1 == (iRet = poll(&Poll, 1, iTimeout)) && errno == EINTR) { } TRACE("Woken up from poll() with ret=%d [iTimeout=%d]\n", iRet, iTimeout); @@ -1937,7 +1937,7 @@ namespace CorUnix } #endif // HAVE_KQUEUE - while (-1 == (iRet = read(m_iProcessPipeRead, pPos, iBytes - iBytesRead)) && errno == EINTR); + while (-1 == (iRet = read(m_iProcessPipeRead, pPos, iBytes - iBytesRead)) && errno == EINTR) { } if (0 == iRet) { @@ -2721,7 +2721,7 @@ namespace CorUnix /* create the pipe, with full access to the owner only */ int mkfifo_result; - while (-1 == (mkfifo_result = mkfifo(szPipeFilename, S_IRWXU)) && errno == EINTR); + while (-1 == (mkfifo_result = mkfifo(szPipeFilename, S_IRWXU)) && errno == EINTR) { } if (mkfifo_result == -1) { if (errno == EEXIST) @@ -2729,7 +2729,7 @@ namespace CorUnix /* Some how no one deleted the pipe, perhaps it was left behind from a crash?? Delete the pipe and try again. */ int unlink_result; - while (-1 == (unlink_result = unlink(szPipeFilename)) && errno == EINTR); + while (-1 == (unlink_result = unlink(szPipeFilename)) && errno == EINTR) { } if (-1 == unlink_result) { ERROR( "Unable to delete the process pipe that was left behind.\n" ); @@ -2738,7 +2738,7 @@ namespace CorUnix } else { - while (-1 == (mkfifo_result = mkfifo(szPipeFilename, S_IRWXU)) && errno == EINTR); + while (-1 == (mkfifo_result = mkfifo(szPipeFilename, S_IRWXU)) && errno == EINTR) { } if (mkfifo_result == -1) { ERROR( "Still unable to create the process pipe...giving up!\n" ); @@ -2787,8 +2787,8 @@ namespace CorUnix goto CPP_exit; } #if !HAVE_PIPE2 - while (-1 == fcntl(rgiPipe[0], F_SETFD, FD_CLOEXEC) && errno == EINTR); // make pipe non-inheritable, if possible - while (-1 == fcntl(rgiPipe[1], F_SETFD, FD_CLOEXEC) && errno == EINTR); + while (-1 == fcntl(rgiPipe[0], F_SETFD, FD_CLOEXEC) && errno == EINTR) { } // make pipe non-inheritable, if possible + while (-1 == fcntl(rgiPipe[1], F_SETFD, FD_CLOEXEC) && errno == EINTR) { } #endif // !HAVE_PIPE2 #endif // !CORECLR @@ -2823,7 +2823,7 @@ namespace CorUnix // Failed if (0 != szPipeFilename[0]) { - while (-1 == unlink(szPipeFilename) && errno == EINTR); + while (-1 == unlink(szPipeFilename) && errno == EINTR) { } } if (-1 != iPipeRd) { @@ -2872,7 +2872,7 @@ namespace CorUnix if (GetProcessPipeName(szPipeFilename, MAX_PATH, gPID)) { int unlink_result; - while (-1 == (unlink_result = unlink(szPipeFilename)) && errno == EINTR); + while (-1 == (unlink_result = unlink(szPipeFilename)) && errno == EINTR) { } if (unlink_result == -1) { ERROR("Unable to unlink the pipe file name errno=%d (%s)\n", @@ -3122,7 +3122,7 @@ namespace CorUnix ERROR("Failed creating thread synchronization mutex [error=%d (%s)]\n", iRet, strerror(iRet)); if (EAGAIN == iRet && MaxUnavailableResourceRetries >= ++iEagains) { - while (-1 == poll(NULL, 0, std::min(100,10*iEagains)) && errno == EINTR); + while (-1 == poll(NULL, 0, std::min(100,10*iEagains)) && errno == EINTR) { } goto Mutex_retry; } else if (ENOMEM == iRet) @@ -3148,7 +3148,7 @@ namespace CorUnix "[error=%d (%s)]\n", iRet, strerror(iRet)); if (EAGAIN == iRet && MaxUnavailableResourceRetries >= ++iEagains) { - while (-1 == poll(NULL, 0, std::min(100,10*iEagains)) && errno == EINTR); + while (-1 == poll(NULL, 0, std::min(100,10*iEagains)) && errno == EINTR) { } goto Cond_retry; } else if (ENOMEM == iRet) diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index 6554a433986ed4..92bdd139c6d62d 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -347,7 +347,7 @@ ipc_socket_create_uds (DiagnosticsIpc *ipc) if (new_socket != DS_IPC_INVALID_SOCKET) { int fcntl_result; - while (-1 == (fcntl_result = fcntl (new_socket, F_SETFD, FD_CLOEXEC)) && errno == EINTR); // ignore any failures; this is best effort + while (-1 == (fcntl_result = fcntl (new_socket, F_SETFD, FD_CLOEXEC)) && errno == EINTR) { } // ignore any failures; this is best effort } #endif // SOCK_CLOEXEC DS_EXIT_BLOCKING_PAL_SECTION; @@ -378,7 +378,7 @@ ipc_socket_create_tcp (DiagnosticsIpc *ipc) if (new_socket != DS_IPC_INVALID_SOCKET) { #ifndef SOCK_CLOEXEC #ifndef HOST_WIN32 - while (-1 == fcntl (new_socket, F_SETFD, FD_CLOEXEC) && errno == EINTR); // ignore any failures; this is best effort + while (-1 == fcntl (new_socket, F_SETFD, FD_CLOEXEC) && errno == EINTR) { } // ignore any failures; this is best effort #endif // HOST_WIN32 #endif // SOCK_CLOEXEC int option_value = 1; @@ -460,11 +460,11 @@ ipc_socket_set_blocking ( u_long blocking_mode = blocking ? 0 : 1; result = ioctlsocket (s, FIONBIO, &blocking_mode); #else - while (-1 == (result = fcntl (s, F_GETFL, 0)) && errno == EINTR); + while (-1 == (result = fcntl (s, F_GETFL, 0)) && errno == EINTR) { } if (result != -1) { int value = blocking ? (result & (~O_NONBLOCK)) : (result | (O_NONBLOCK)); - while (-1 == (result = fcntl (s, F_SETFL, value)) && errno == EINTR); + while (-1 == (result = fcntl (s, F_SETFL, value)) && errno == EINTR) { } } #endif DS_EXIT_BLOCKING_PAL_SECTION; @@ -568,7 +568,7 @@ ipc_socket_accept ( if (client_socket != -1) { // ignore any failures; this is best effort - while (-1 == fcntl (client_socket, F_SETFD, FD_CLOEXEC) && errno == EINTR); + while (-1 == fcntl (client_socket, F_SETFD, FD_CLOEXEC) && errno == EINTR) { } } #endif #endif @@ -1207,7 +1207,7 @@ ds_ipc_listen ( #ifdef DS_IPC_PAL_AF_UNIX int result_unlink; DS_ENTER_BLOCKING_PAL_SECTION; - while (-1 == (result_unlink = unlink (((struct sockaddr_un *)ipc->server_address)->sun_path)) && errno == EINTR); + while (-1 == (result_unlink = unlink (((struct sockaddr_un *)ipc->server_address)->sun_path)) && errno == EINTR) { } DS_EXIT_BLOCKING_PAL_SECTION; EP_ASSERT (result_unlink != -1); @@ -1349,7 +1349,7 @@ ds_ipc_close ( // reference to it is closed." - unix(7) man page int result_unlink; DS_ENTER_BLOCKING_PAL_SECTION; - while (-1 == (result_unlink = unlink (((struct sockaddr_un *)ipc->server_address)->sun_path)) && errno == EINTR); + while (-1 == (result_unlink = unlink (((struct sockaddr_un *)ipc->server_address)->sun_path)) && errno == EINTR) { } DS_EXIT_BLOCKING_PAL_SECTION; if (result_unlink == -1) { @@ -1599,7 +1599,7 @@ ds_ipc_stream_read_fd ( msg.msg_controllen = sizeof(control); ssize_t res; - while ((res = recvmsg(ipc_stream->client_socket, &msg, 0)) < 0 && errno == EINTR); + while ((res = recvmsg(ipc_stream->client_socket, &msg, 0)) < 0 && errno == EINTR) { } if (res < 0) return false; diff --git a/src/native/libs/System.Native/pal_ifaddrs.c b/src/native/libs/System.Native/pal_ifaddrs.c index d5d59ab932047e..98b22d59456816 100644 --- a/src/native/libs/System.Native/pal_ifaddrs.c +++ b/src/native/libs/System.Native/pal_ifaddrs.c @@ -137,7 +137,7 @@ static int send_netlink_dump_request(struct netlink_session *session, int type) session->message_header.msg_iovlen = 1; session->message_header.msg_iov = &session->payload_vector; - int sendmsg_result; + ssize_t sendmsg_result; while (-1 == (sendmsg_result = sendmsg(session->sock_fd, (const struct msghdr*)&session->message_header, 0)) && errno == EINTR); if (sendmsg_result < 0) { LOG_WARN("Failed to send netlink message. %s\n", strerror(errno)); From b2952f50783aff0dbf39867f9e882a3623b435c2 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 7 Oct 2025 21:54:43 +1100 Subject: [PATCH 46/50] Remove unrelated whitespace changes VSC added --- src/coreclr/minipal/Unix/doublemapping.cpp | 8 ++++---- src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp | 2 +- src/coreclr/pal/src/thread/process.cpp | 2 +- src/mono/mono/profiler/log.c | 2 +- src/native/eventpipe/ep-session.c | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/coreclr/minipal/Unix/doublemapping.cpp b/src/coreclr/minipal/Unix/doublemapping.cpp index b3f907428c10e3..1a12ba3191e3f8 100644 --- a/src/coreclr/minipal/Unix/doublemapping.cpp +++ b/src/coreclr/minipal/Unix/doublemapping.cpp @@ -83,7 +83,7 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu } #endif uint64_t maxDoubleMappedMemorySize = MaxDoubleMappedSize; - + // Set the maximum double mapped memory size to the size of the physical memory long pages = sysconf(_SC_PHYS_PAGES); if (pages != -1) @@ -370,7 +370,7 @@ static int InitializeTemplateThunkMappingDataPhdrCallback(struct dl_phdr_info *i { return -1; // Opening the image didn't work } - + locals->data.fdImage = fdImage; locals->data.offsetInFileOfStartOfSection = info->dlpi_phdr[j].p_offset; locals->data.addrOfStartOfSection = baseSectionAddr; @@ -414,7 +414,7 @@ TemplateThunkMappingData *InitializeTemplateThunkMappingData(void* pTemplate) int fd = memfd_create("doublemapper-template", MFD_CLOEXEC); #else int fd = -1; - + #ifndef TARGET_ANDROID // Bionic doesn't have shm_{open,unlink} // POSIX fallback @@ -456,7 +456,7 @@ TemplateThunkMappingData *InitializeTemplateThunkMappingData(void* pTemplate) TemplateThunkMappingData *pAllocatedData = (TemplateThunkMappingData*)malloc(sizeof(TemplateThunkMappingData)); *pAllocatedData = locals.data; - TemplateThunkMappingData *pExpectedNull = NULL; + TemplateThunkMappingData *pExpectedNull = NULL; if (__atomic_compare_exchange_n (&s_pThunkData, &pExpectedNull, pAllocatedData, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)) { return pAllocatedData; diff --git a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp index 8f60937930c39a..c21888935457f6 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp @@ -55,7 +55,7 @@ // Crash dump generating program arguments. MAX_ARGV_ENTRIES is the max number // of entries if every createdump option/argument is passed. -#define MAX_ARGV_ENTRIES 32 +#define MAX_ARGV_ENTRIES 32 const char* g_argvCreateDump[MAX_ARGV_ENTRIES] = { nullptr }; char* g_szCreateDumpPath = nullptr; char* g_ppidarg = nullptr; diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 2df6f73d93e9f5..70c9a5777ca6de 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -2495,7 +2495,7 @@ PROCCreateCrashDump( int bytesRead; while((bytesRead = read(child_read_pipe, &buffer, 1)) < 0 && errno == EINTR); close(child_read_pipe); - + if (bytesRead != 1) { fprintf(stderr, "Problem reading from createdump child_read_pipe: %s (%d)\n", strerror(errno), errno); diff --git a/src/mono/mono/profiler/log.c b/src/mono/mono/profiler/log.c index a7c7c4217eab75..b4869343f4d87e 100644 --- a/src/mono/mono/profiler/log.c +++ b/src/mono/mono/profiler/log.c @@ -3838,4 +3838,4 @@ proflog_trigger_heapshot (void) while (handle_writer_queue_entry ()); while (handle_dumper_queue_entry ()); -} +} \ No newline at end of file diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 6255050b11a642..1ac8f53e033c3d 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -260,7 +260,7 @@ session_user_events_tracepoints_init ( EP_ASSERT (session_provider != NULL); ep_raise_error_if_nok (ep_session_provider_register_tracepoints (session_provider, session->user_events_data_fd)); } DN_LIST_FOREACH_END; - + result = true; ep_on_exit: @@ -401,7 +401,7 @@ ep_session_remove_dangling_session_states (EventPipeSession *session) EventPipeThreadSessionState *session_state = ep_thread_get_session_state(thread, session); if (session_state) { // If a buffer tries to write event(s) but never gets a buffer because the maximum total buffer size - // has been exceeded, we can leak the EventPipeThreadSessionState* and crash later trying to access + // has been exceeded, we can leak the EventPipeThreadSessionState* and crash later trying to access // the session from the thread session state. Whenever we terminate a session we check to make sure // we haven't leaked any thread session states. ep_thread_delete_session_state(thread, session); From 9d34503d0f25dbf1c1beaf27d78fab384c714018 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 7 Oct 2025 21:56:07 +1100 Subject: [PATCH 47/50] Fix compile error --- src/native/eventpipe/ep-session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 1ac8f53e033c3d..9c51e0c9f91600 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -908,7 +908,7 @@ session_tracepoint_write_event ( bytes_written_total += bytes_written; while (iovcnt > 0 && bytes_written > 0) { - if (iov->iov_len >= bytes_written) + if (iov->iov_len >= (size_t)bytes_written) { bytes_written -= iov->iov_len; iovcnt--; From a130b6890a6ebbe66ef15b0a0f227a9ddb38b1d9 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Tue, 7 Oct 2025 21:58:11 +1100 Subject: [PATCH 48/50] Remove unrelated whitespace changes VSC added --- src/native/eventpipe/ep-session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 9c51e0c9f91600..b358cc0d80d5a3 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -720,7 +720,7 @@ construct_extension_activity_ids_buffer ( memcpy (extension + offset, activity_id, EP_ACTIVITY_ID_SIZE); offset += EP_ACTIVITY_ID_SIZE; } - + EP_ASSERT ((size_t)(offset + 1 + EP_ACTIVITY_ID_SIZE) <= extension_size); if (!related_activity_id_is_empty) { extension[offset] = 0x03; From 80e458173ab635197612318cbe932580e7375396 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Wed, 8 Oct 2025 07:23:07 +1100 Subject: [PATCH 49/50] Fix compile error --- src/coreclr/debug/createdump/crashinfounix.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfounix.cpp b/src/coreclr/debug/createdump/crashinfounix.cpp index d27a38d1244a47..d9e1484a122acc 100644 --- a/src/coreclr/debug/createdump/crashinfounix.cpp +++ b/src/coreclr/debug/createdump/crashinfounix.cpp @@ -191,9 +191,9 @@ CrashInfo::GetAuxvEntries() size_t readSoFar = 0; while (readSoFar < sizeof(elf_aux_entry)) { - size_t readResult; + ssize_t readResult; while (-1 == (readResult = read(fd, (unsigned char*)&auxvEntry + readSoFar, sizeof(elf_aux_entry) - readSoFar) && errno == EINTR)); - if (readResult == (size_t) -1) + if (readResult == -1) { break; } @@ -201,7 +201,7 @@ CrashInfo::GetAuxvEntries() { break; } - readSoFar += readResult; + readSoFar += (size_t)readResult; } if (readSoFar != sizeof(elf_aux_entry)) break; m_auxvEntries.push_back(auxvEntry); From f83da6206abaad0790608daace051988a5810cf1 Mon Sep 17 00:00:00 2001 From: Hamish Arblaster Date: Wed, 8 Oct 2025 07:40:14 +1100 Subject: [PATCH 50/50] Fix compile error --- src/coreclr/debug/createdump/crashinfo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index fb074825c51b8e..de53ccb90b81bb 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -826,9 +826,9 @@ CrashInfo::PageMappedToPhysicalMemory(uint64_t start) size_t readSoFar = 0; while (readSoFar < sizeof(value)) { - size_t readResult; + ssize_t readResult; while (-1 == (readResult = read(m_fdPagemap, (unsigned char*)&value + readSoFar, sizeof(value) - readSoFar) && errno == EINTR)); - if (readResult == (size_t) -1) + if (readResult == -1) { int readErrno = errno; TRACE("Reading of pagemap file FAILED, addr: %" PRIA PRIx ", pagemap offset: %" PRIA PRIx ", size: %zu, ERRNO %d: %s\n", start, pagemapOffset, sizeof(value), readErrno, strerror(readErrno)); @@ -839,7 +839,7 @@ CrashInfo::PageMappedToPhysicalMemory(uint64_t start) TRACE("Reading of pagemap file FAILED, addr: %" PRIA PRIx ", pagemap offset: %" PRIA PRIx ", size: %zu, Read Was Incomplete\n", start, pagemapOffset, sizeof(value)); return true; } - readSoFar += readResult; + readSoFar += (size_t)readResult; } bool is_page_present = (value & ((uint64_t)1 << 63)) != 0;