diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index 8958cfc05c54f3..de53ccb90b81bb 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -814,20 +814,32 @@ 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)); 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; + ssize_t readResult; + while (-1 == (readResult = read(m_fdPagemap, (unsigned char*)&value + readSoFar, sizeof(value) - readSoFar) && errno == EINTR)); + 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)); + 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 += (size_t)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 b0bcb0b8c2d3b8..d9e1484a122acc 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)); @@ -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) @@ -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); @@ -121,8 +123,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) { @@ -130,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 { @@ -166,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); @@ -175,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)) + { + ssize_t readResult; + while (-1 == (readResult = read(fd, (unsigned char*)&auxvEntry + readSoFar, sizeof(elf_aux_entry) - readSoFar) && errno == EINTR)); + if (readResult == -1) + { + break; + } + if (readResult == 0) + { + break; + } + readSoFar += (size_t)readResult; + } + if (readSoFar != sizeof(elf_aux_entry)) break; m_auxvEntries.push_back(auxvEntry); if (auxvEntry.a_type == AT_NULL) { @@ -532,7 +559,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/debug/createdump/crashreportwriter.cpp b/src/coreclr/debug/createdump/crashreportwriter.cpp index 5a90e55c11273c..8e4c89f5ae6b2e 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); } } @@ -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/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/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 c94efcd18397e2..bd1f718eea0ba9 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 @@ -22,19 +23,22 @@ 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) + int mkfifo_result; + while (-1 == (mkfifo_result = mkfifo(m_inPipeName, S_IRWXU)) && errno == EINTR); + if (mkfifo_result == -1) { return false; } - unlink(m_outPipeName); + 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) { - unlink(m_inPipeName); + while (-1 == unlink(m_inPipeName) && errno == EINTR); return false; } @@ -57,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); @@ -84,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); @@ -113,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) @@ -140,8 +146,10 @@ int TwoWayPipe::Write(const void *data, DWORD dataSize) int bytesWritten; int cb = dataSize; - while ((bytesWritten = (int)write(m_outboundPipe, data, cb)) > 0) + while (true) { + 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) @@ -166,8 +174,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 +186,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/gc/unix/cgroup.cpp b/src/coreclr/gc/unix/cgroup.cpp index ff1712235a339d..7912a574adfdec 100644 --- a/src/coreclr/gc/unix/cgroup.cpp +++ b/src/coreclr/gc/unix/cgroup.cpp @@ -127,7 +127,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/gc/unix/numasupport.cpp b/src/coreclr/gc/unix/numasupport.cpp index 17e2764f456e2d..6b66b2e0868b58 100644 --- a/src/coreclr/gc/unix/numasupport.cpp +++ b/src/coreclr/gc/unix/numasupport.cpp @@ -28,11 +28,19 @@ 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 ((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 09d6086e983d9c..176e65b1465d18 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -443,7 +443,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; @@ -467,12 +469,15 @@ 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; 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; @@ -506,7 +511,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 {}; @@ -514,8 +521,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/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/minipal/Unix/doublemapping.cpp b/src/coreclr/minipal/Unix/doublemapping.cpp index 205a2cac789fae..1a12ba3191e3f8 100644 --- a/src/coreclr/minipal/Unix/doublemapping.cpp +++ b/src/coreclr/minipal/Unix/doublemapping.cpp @@ -71,9 +71,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 @@ -122,7 +122,9 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu } } - if (ftruncate(fd, maxDoubleMappedMemorySize) == -1) + int ftruncate_result; + while (-1 == (ftruncate_result = ftruncate(fd, maxDoubleMappedMemorySize)) && errno == EINTR); + if (ftruncate_result == -1) { close(fd); return false; @@ -421,16 +423,18 @@ 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 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/nativeaot/Runtime/unix/PalCreateDump.cpp b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp index a8acc1b9f676c0..c21888935457f6 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp @@ -214,7 +214,13 @@ CreateCrashDump( int cbErrorMessageBuffer) { int pipe_descs[4]; - if (pipe(pipe_descs) == -1 || pipe(pipe_descs + 2) == -1) + int pipe_result = 0; + while (-1 == (pipe_result = pipe(pipe_descs)) && errno == EINTR); + if (pipe_result != -1) + { + while (-1 == (pipe_result = pipe(pipe_descs + 2)) && errno == EINTR); + } + if (pipe_result == -1) { if (errorMessageBuffer != nullptr) { @@ -266,7 +272,7 @@ CreateCrashDump( // Only dup the child's stderr if there is error buffer if (errorMessageBuffer != nullptr) { - dup2(child_write_pipe, STDERR_FILENO); + while (-1 == dup2(child_write_pipe, STDERR_FILENO) && errno == EINTR); } // Execute the createdump program if (execv(argv[0], (char* const *)argv) == -1) @@ -312,8 +318,10 @@ CreateCrashDump( // Read createdump's stderr int bytesRead = 0; int count = 0; - while ((count = read(parent_read_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0) + while (true) { + while (-1 == (count = read(parent_read_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) && errno == EINTR); + if (count <= 0) break; bytesRead += count; } errorMessageBuffer[bytesRead] = 0; @@ -326,7 +334,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", @@ -605,7 +614,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/nativeaot/Runtime/unix/PalUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp index 873ae69c28ddf5..3e208696eb443c 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp @@ -854,7 +854,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/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/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 732d1d5db05933..7e7790b9468f0e 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -654,9 +654,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) { @@ -667,7 +680,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) @@ -684,12 +706,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/directory.cpp b/src/coreclr/pal/src/file/directory.cpp index e06afd0b19e1c2..93ad5e4d5fb2aa 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. */ @@ -455,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); @@ -522,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 ) { @@ -534,7 +538,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 fab78b1299467b..3fb7a987f29a5e 100644 --- a/src/coreclr/pal/src/file/file.cpp +++ b/src/coreclr/pal/src/file/file.cpp @@ -201,9 +201,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; @@ -523,7 +528,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 @@ -611,7 +618,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)); @@ -634,7 +643,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)); @@ -716,7 +727,9 @@ CorUnix::InternalCreateFile( } if (bFileCreated) { - if (-1 == unlink(lpUnixPath)) + int unlink_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)); @@ -945,7 +958,7 @@ DeleteFileA( } } - result = unlink( lpFullunixFileName ); + while (-1 == (result = unlink( lpFullunixFileName )) && errno == EINTR); if (result < 0) { @@ -1111,7 +1124,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 ) @@ -1467,7 +1480,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", @@ -1494,7 +1507,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 @@ -1511,9 +1524,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 @@ -1521,7 +1536,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 @@ -1773,7 +1788,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(); @@ -2156,7 +2173,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; @@ -2165,14 +2184,17 @@ 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)) + 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)); @@ -2415,7 +2437,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/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index d06cd1a4963fe2..9370f4d544a409 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -1130,7 +1130,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 76fdb966afb6ac..8e020843573cab 100644 --- a/src/coreclr/pal/src/loader/module.cpp +++ b/src/coreclr/pal/src/loader/module.cpp @@ -1082,7 +1082,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/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 8900ccd1058c01..2ca72367fb2be3 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 @@ -195,7 +196,7 @@ FileMappingCleanupRoutine( if (pImmutableData->bPALCreatedTempFile) { - unlink(pImmutableData->lpFileName); + while (-1 == unlink(pImmutableData->lpFileName) && errno == EINTR); } if (FALSE == fShutdown) @@ -467,7 +468,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" ); @@ -519,7 +520,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 +601,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; @@ -651,7 +656,7 @@ CorUnix::InternalCreateFileMapping( if (bPALCreatedTempFile) { - unlink(pImmutableData->lpFileName); + while (-1 == unlink(pImmutableData->lpFileName) && errno == EINTR); } if (-1 != UnixFd) @@ -1489,8 +1494,8 @@ 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 ); - fstat( UnixFD, &FileInfo ); + while (-1 == (TruncateRetVal = ftruncate( UnixFD, NewSize )) && errno == EINTR); + while (-1 == fstat( UnixFD, &FileInfo ) && errno == EINTR); if ( TruncateRetVal != 0 || FileInfo.st_size != NewSize ) { @@ -1502,8 +1507,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", @@ -1518,35 +1526,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, (size_t)BUFFER_SIZE) )) && errno == EINTR); + if (writeResult == -1) { ERROR( "Unable to grow the file. Reason=%s\n", strerror( errno ) ); if((errno == ENOSPC) || (errno == EDQUOT)) @@ -1559,10 +1544,24 @@ 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 */ - lseek( UnixFD, CurrentPosition, SEEK_SET ); + while (-1 == lseek( UnixFD, CurrentPosition, SEEK_SET ) && errno == EINTR); } done: @@ -1970,9 +1969,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 = (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); + 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(); } @@ -2082,16 +2108,57 @@ 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; + 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); + 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; + } + 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); + 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)) diff --git a/src/coreclr/pal/src/misc/cgroup.cpp b/src/coreclr/pal/src/misc/cgroup.cpp index f4110c08ff42cb..ace3063289bd71 100644 --- a/src/coreclr/pal/src/misc/cgroup.cpp +++ b/src/coreclr/pal/src/misc/cgroup.cpp @@ -91,7 +91,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/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 84680cc2b4ffed..b260f48d2ce948 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__) @@ -218,12 +219,23 @@ struct PerfJitDumpState fd = result; - result = write(fd, &header, 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); + if (result == -1) break; + messageSize -= result; + message += result; + if (messageSize == 0) break; + } - if (result == -1) + if (result == -1 || messageSize != 0) return FatalError(); - result = fsync(fd); + while (-1 == (result = fsync(fd)) && errno == EINTR); if (result == -1) return FatalError(); @@ -349,7 +361,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/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 71873fbec82579..15e13884009d87 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" @@ -178,7 +179,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) @@ -195,7 +197,8 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( if (isGlobalLockAcquired) { - int operationResult = mkdir(path, permissionsMask); + int operationResult; + while (-1 == (operationResult = mkdir(path, permissionsMask)) && errno == EINTR); if (operationResult != 0) { if (errors != nullptr) @@ -226,7 +229,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( GetFriendlyErrorCodeString(errorCode)); } - rmdir(path); + while (-1 == rmdir(path) && errno == EINTR); throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } @@ -264,19 +267,21 @@ bool SharedMemoryHelpers::EnsureDirectoryExists( GetFriendlyErrorCodeString(errorCode)); } - rmdir(tempPath); + while (-1 == rmdir(tempPath) && errno == EINTR); 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; } // 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 == rmdir(tempPath) && errno == EINTR); + while (-1 == (statResult = stat(path, &statInfo)) && errno == EINTR); } // If the path exists, check that it's a directory @@ -481,7 +486,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) @@ -568,7 +574,7 @@ int SharedMemoryHelpers::CreateOrOpenFile( } CloseFile(fileDescriptor); - unlink(path); + while (-1 == unlink(path) && errno == EINTR); throw SharedMemoryException(static_cast(SharedMemoryError::IO)); } @@ -605,9 +611,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) { @@ -717,7 +730,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; @@ -1029,14 +1043,14 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( if (m_createdFile) { _ASSERTE(m_filePath != nullptr); - unlink(*m_filePath); + while (-1 == unlink(*m_filePath) && errno == EINTR); } if (m_sessionDirectoryPathCharCount != 0) { _ASSERTE(*m_filePath != nullptr); m_filePath->CloseBuffer(m_sessionDirectoryPathCharCount); - rmdir(*m_filePath); + while (-1 == rmdir(*m_filePath) && errno == EINTR); } if (m_acquiredCreationDeletionFileLockForId != nullptr) @@ -1387,9 +1401,9 @@ 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); + while (-1 == rmdir(path) && errno == EINTR); } catch (SharedMemoryException) { diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index 0665df179caa04..031cadc259290c 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) { @@ -1849,7 +1850,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); @@ -1936,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) { @@ -2164,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)) { @@ -2718,13 +2720,17 @@ 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) { /* 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; @@ -2732,7 +2738,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; @@ -2765,12 +2772,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"); @@ -2778,8 +2787,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 @@ -2814,7 +2823,7 @@ namespace CorUnix // Failed if (0 != szPipeFilename[0]) { - unlink(szPipeFilename); + while (-1 == unlink(szPipeFilename) && errno == EINTR) { } } if (-1 != iPipeRd) { @@ -2862,7 +2871,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)); @@ -3111,7 +3122,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 +3148,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/coreclr/pal/src/synchobj/mutex.cpp b/src/coreclr/pal/src/synchobj/mutex.cpp index 4e5f7f8852106a..1f0ea405325210 100644 --- a/src/coreclr/pal/src/synchobj/mutex.cpp +++ b/src/coreclr/pal/src/synchobj/mutex.cpp @@ -1154,14 +1154,14 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen( if (m_createdLockFile) { _ASSERTE(m_lockFilePath != nullptr); - unlink(*m_lockFilePath); + while (-1 == unlink(*m_lockFilePath) && errno == EINTR); } if (m_sessionDirectoryPathCharCount != 0) { _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 @@ -1423,9 +1423,9 @@ 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); + while (-1 == rmdir(path) && errno == EINTR); } catch (SharedMemoryException) { diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 12ba9ac544f849..70c9a5777ca6de 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -452,7 +452,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); @@ -761,7 +761,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; @@ -883,19 +885,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); @@ -1003,7 +1009,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)); @@ -1013,7 +1021,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)); @@ -1023,7 +1033,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)); @@ -2433,7 +2445,13 @@ PROCCreateCrashDump( } int pipe_descs[4]; - if (pipe(pipe_descs) == -1 || pipe(pipe_descs + 2) == -1) + int pipe_result; + while (-1 == (pipe_result = pipe(pipe_descs)) && errno == EINTR); + if (pipe_result != -1) + { + while (-1 == (pipe_result = pipe(pipe_descs + 2)) && errno == EINTR); + } + if (pipe_result == -1) { if (errorMessageBuffer != nullptr) { @@ -2488,7 +2506,7 @@ PROCCreateCrashDump( // Only dup the child's stderr if there is error buffer if (errorMessageBuffer != nullptr) { - dup2(child_write_pipe, STDERR_FILENO); + while (-1 == dup2(child_write_pipe, STDERR_FILENO) && errno == EINTR); } if (g_createdumpCallback != nullptr) { @@ -2548,8 +2566,10 @@ PROCCreateCrashDump( // Read createdump's stderr int bytesRead = 0; int count = 0; - while ((count = read(parent_read_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0) + while (true) { + while (-1 == (count = read(parent_read_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) && errno == EINTR); + if (count <= 0) break; bytesRead += count; } errorMessageBuffer[bytesRead] = 0; @@ -2562,7 +2582,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", @@ -3613,7 +3634,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: @@ -3832,7 +3854,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/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index 0af33b35734634..9f77f0e90d309d 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -1383,7 +1383,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)); @@ -1393,11 +1393,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/coreclr/pal/src/thread/threadsusp.cpp b/src/coreclr/pal/src/thread/threadsusp.cpp index 867f46b3fa38f2..bfa9e2f09647c2 100644 --- a/src/coreclr/pal/src/thread/threadsusp.cpp +++ b/src/coreclr/pal/src/thread/threadsusp.cpp @@ -74,20 +74,22 @@ CThreadSuspensionInfo::InternalSuspendNewThreadFromData( ReleaseSuspensionLock(pThread); int pipe_descs[2]; - int pipeRv = + 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) { ERROR("pipe() failed! error is %d (%s)\n", errno, strerror(errno)); 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/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); 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..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; @@ -71,9 +73,13 @@ 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) + 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 @@ -81,5 +87,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; } diff --git a/src/coreclr/tools/superpmi/mcs/verbmerge.cpp b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp index 35b7263d4a68b7..049e20d67c830a 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 "config.h" #include #ifdef TARGET_UNIX @@ -281,18 +282,22 @@ 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) { while (true) { dirent *pEntry; int dirEntryType; - - errno = 0; - pEntry = readdir(pDir); - if (pEntry == nullptr) - break; + do + { + errno = 0; + pEntry = readdir(pDir); + } + while (pEntry == nullptr && errno == EINTR); + if (pEntry == nullptr) break; #if HAVE_DIRENT_D_TYPE dirEntryType = pEntry->d_type; @@ -438,7 +443,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; @@ -514,7 +519,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); @@ -717,7 +723,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-shared/methodcontextreader.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp index 3165ac8ab73436..b0e39d8de3ce39 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/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 3cd51abf6f6bfc..cec4654f2909a7 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); } @@ -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())); @@ -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 */ @@ -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); } @@ -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/component/debugger-poll.c b/src/mono/mono/component/debugger-poll.c index b914c7bdde05e2..6d32f900e27c28 100644 --- a/src/mono/mono/component/debugger-poll.c +++ b/src/mono/mono/component/debugger-poll.c @@ -42,7 +42,9 @@ 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); + return result; } #else diff --git a/src/mono/mono/eglib/gfile-posix.c b/src/mono/mono/eglib/gfile-posix.c index f38db70c6a7b27..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; @@ -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 78815dc9c82bdd..8b92f0c0156652 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) @@ -78,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; } @@ -86,13 +92,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; } @@ -117,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/gfile.c b/src/mono/mono/eglib/gfile.c index 5720a54a712658..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 } @@ -189,6 +191,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/gpath.c b/src/mono/mono/eglib/gpath.c index 96e39c3588dddd..3eab361543b711 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; } @@ -289,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/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/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 (); 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 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/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/cfgdump.c b/src/mono/mono/mini/cfgdump.c index 64e0377f45caa8..3b6646362090ba 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; } @@ -79,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/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 4c36fd6b3ffeea..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"); @@ -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 } @@ -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 7cf63847ff61b9..f9c890bd5ccc8a 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/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 24d3834296604f..b4869343f4d87e 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); } @@ -2522,7 +2525,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; @@ -2868,7 +2873,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 @@ -2897,7 +2903,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/mono/mono/sgen/sgen-protocol.c b/src/mono/mono/sgen/sgen-protocol.c index 7cfca07f14da8b..a7d0e2778e8a28 100644 --- a/src/mono/mono/sgen/sgen-protocol.c +++ b/src/mono/mono/sgen/sgen-protocol.c @@ -102,18 +102,21 @@ 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 */ + } 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); @@ -259,7 +262,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/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/mono/mono/utils/dlmalloc.c b/src/mono/mono/utils/dlmalloc.c index 972c7a61af4ed7..964010b45653f3 100644 --- a/src/mono/mono/utils/dlmalloc.c +++ b/src/mono/mono/utils/dlmalloc.c @@ -1323,8 +1323,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 */ @@ -2456,10 +2461,18 @@ 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 && - read(fd, buf, sizeof(buf)) == sizeof(buf)) { + while (-1 == (fd = open("/dev/urandom", O_RDONLY)) && errno == EINTR); + 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-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/mono/mono/utils/mono-filemap.c b/src/mono/mono/utils/mono-filemap.c index 0c4ac46a5b4970..639b09101934c4 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 @@ -37,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; @@ -48,7 +50,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; } @@ -88,20 +92,29 @@ 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) + size_t readSoFar = 0; + while (readSoFar < length) + { + while (-1 == (bytes_read = read (fd, (unsigned char*)ptr + readSoFar, length - readSoFar)) && errno == EINTR); + if (bytes_read <= 0) break; + readSoFar += bytes_read; + } + if (readSoFar != 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/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 d20bb3c903f727..90b6c562369c3b 100644 --- a/src/mono/mono/utils/mono-proclib.c +++ b/src/mono/mono/utils/mono-proclib.c @@ -83,16 +83,27 @@ 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 * 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/mono/wasi/runtime/driver.c b/src/mono/wasi/runtime/driver.c index b9f01df2c659af..df2e94669e21db 100644 --- a/src/mono/wasi/runtime/driver.c +++ b/src/mono/wasi/runtime/driver.c @@ -227,7 +227,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.h b/src/native/corehost/hostmisc/pal.h index 77b1dd578676e4..4cd525e0774918 100644 --- a/src/native/corehost/hostmisc/pal.h +++ b/src/native/corehost/hostmisc/pal.h @@ -261,7 +261,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; @@ -269,9 +271,27 @@ namespace pal return false; } - 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 remove(const char_t* path) { return ::remove(path); } + 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) + { + int result; + while (-1 == (result = ::rename(old_name, new_name)) && errno == EINTR); + return result; + } + + 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/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp index 4a6197f541c4eb..4e1e7aa443de4e 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); @@ -81,7 +83,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); @@ -400,7 +404,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; } @@ -1011,7 +1017,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); @@ -1023,12 +1031,22 @@ 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; - 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/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index c668c0851f070d..92bdd139c6d62d 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; @@ -457,9 +460,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; @@ -562,7 +568,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 @@ -1201,7 +1207,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); @@ -1343,7 +1349,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) { @@ -1593,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/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/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 0d6c62c3bce964..b358cc0d80d5a3 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -898,8 +898,32 @@ 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); - if (should_write_metadata && (bytes_written == io_bytes_to_write)) + 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 >= (size_t)bytes_written) + { + bytes_written -= iov->iov_len; + iovcnt--; + iov++; + } + else + { + iov->iov_len -= bytes_written; + iov->iov_base = (unsigned char*)iov->iov_base + bytes_written; + break; + } + } + } + + 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) 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 221d12d041bbd0..555fe0c8277575 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); int result = close(fd); if (result < 0 && errno == EINTR) result = 0; // on all supported platforms, close(2) returning EINTR still means it was released return result; 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 b51e16c0bbc271..f03fb1b2adcc10 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) { @@ -54,8 +55,16 @@ static void WriteKeypadXmit(void) // write it out to the terminal to enter the mode. if (g_keypadXmit != NULL) { - ssize_t ret; - while (CheckInterrupted(ret = write(g_keypadXmitFd, g_keypadXmit, (size_t)(sizeof(char) * strlen(g_keypadXmit))))); + 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 -= (size_t)ret; + message += ret; + } assert(ret >= 0 || (errno == EBADF && g_keypadXmitFd == 0)); // failure to change the mode should not prevent app from continuing } } @@ -370,7 +379,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; } diff --git a/src/native/libs/System.Native/pal_ifaddrs.c b/src/native/libs/System.Native/pal_ifaddrs.c index e95265afbfa235..6e482a27022066 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) { + 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)); return -1; } @@ -638,7 +640,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) { diff --git a/src/native/libs/System.Native/pal_interfaceaddresses.c b/src/native/libs/System.Native/pal_interfaceaddresses.c index e81e2110860b95..2106f3987f6ac9 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_io.c b/src/native/libs/System.Native/pal_io.c index 23b226d74e0362..1b03dbb156fae2 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) { @@ -335,7 +336,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; @@ -355,8 +356,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 @@ -508,8 +512,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) @@ -615,7 +624,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) @@ -657,7 +668,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; @@ -672,7 +684,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) @@ -682,7 +696,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_mount.c b/src/native/libs/System.Native/pal_mount.c index 386eba5ede1162..a099107955b1e7 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) diff --git a/src/native/libs/System.Native/pal_networking.c b/src/native/libs/System.Native/pal_networking.c index 3b460d4c4e8296..1656e93cac3932 100644 --- a/src/native/libs/System.Native/pal_networking.c +++ b/src/native/libs/System.Native/pal_networking.c @@ -1726,13 +1726,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__) @@ -2852,7 +2857,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; } @@ -3548,7 +3553,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: @@ -3637,8 +3642,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; } @@ -3688,7 +3701,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; } 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) { diff --git a/src/native/libs/System.Native/pal_process.c b/src/native/libs/System.Native/pal_process.c index 129fd612e33168..9c206336ddc57d 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 @@ -491,7 +491,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/libs/System.Security.Cryptography.Native/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c index a20930dc3d0d2c..ff603447967c55 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 @@ -436,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) { @@ -477,8 +479,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)) @@ -1148,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(); } @@ -1263,7 +1273,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); diff --git a/src/native/minipal/debugger.c b/src/native/minipal/debugger.c index 763f12079caabd..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 @@ -65,18 +66,31 @@ 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; } - 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) { @@ -126,18 +140,24 @@ 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; } 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; diff --git a/src/native/minipal/log.c b/src/native/minipal/log.c index d639111a59ddf9..f1b41a98030552 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; @@ -279,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; diff --git a/src/native/minipal/random.c b/src/native/minipal/random.c index 4dae7f4d9c487a..f9f2db4b98cd6e 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)); 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; diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c b/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c index fed141345b8d25..a353efcacda78c 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c @@ -113,7 +113,8 @@ external_assembly_probe(const char* relative_assembly_path, void** data, int64_t 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;