[CAS] Retry blocking syscalls on EINTR (#194691)
Wrap blocking syscalls used by LLVMCAS inside RetryAfterSignal so they are retried on EINTR instead of surfacing as error or silently dropping actions due to failed to acquire locks.
This commit is contained in:
parent
6830f04a25
commit
e9144cc197
3 changed files with 21 additions and 11 deletions
|
|
@ -56,6 +56,7 @@
|
|||
#include "OnDiskCommon.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/CAS/OnDiskCASLogger.h"
|
||||
#include "llvm/Support/Errno.h"
|
||||
|
||||
#if LLVM_ON_UNIX
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -425,7 +426,7 @@ Expected<int64_t> MappedFileRegionArena::allocateOffset(uint64_t AllocSize) {
|
|||
ErrorOr<FileSizeInfo> FileSizeInfo::get(sys::fs::file_t File) {
|
||||
#if LLVM_ON_UNIX && defined(MAPPED_FILE_BSIZE)
|
||||
struct stat Status;
|
||||
int StatRet = ::fstat(File, &Status);
|
||||
int StatRet = sys::RetryAfterSignal(-1, ::fstat, File, &Status);
|
||||
if (StatRet)
|
||||
return errnoAsErrorCode();
|
||||
uint64_t AllocatedSize = uint64_t(Status.st_blksize) * MAPPED_FILE_BSIZE;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OnDiskCommon.h"
|
||||
#include "llvm/Support/Errno.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
|
@ -74,7 +75,9 @@ void cas::ondisk::setMaxMappingSize(uint64_t Size) {
|
|||
std::error_code cas::ondisk::lockFileThreadSafe(int FD,
|
||||
sys::fs::LockKind Kind) {
|
||||
#if HAVE_FLOCK
|
||||
if (flock(FD, Kind == sys::fs::LockKind::Exclusive ? LOCK_EX : LOCK_SH) == 0)
|
||||
if (sys::RetryAfterSignal(
|
||||
-1, flock, FD,
|
||||
Kind == sys::fs::LockKind::Exclusive ? LOCK_EX : LOCK_SH) == 0)
|
||||
return std::error_code();
|
||||
return std::error_code(errno, std::generic_category());
|
||||
#elif defined(_WIN32)
|
||||
|
|
@ -87,7 +90,7 @@ std::error_code cas::ondisk::lockFileThreadSafe(int FD,
|
|||
|
||||
std::error_code cas::ondisk::unlockFileThreadSafe(int FD) {
|
||||
#if HAVE_FLOCK
|
||||
if (flock(FD, LOCK_UN) == 0)
|
||||
if (sys::RetryAfterSignal(-1, flock, FD, LOCK_UN) == 0)
|
||||
return std::error_code();
|
||||
return std::error_code(errno, std::generic_category());
|
||||
#elif defined(_WIN32)
|
||||
|
|
@ -105,8 +108,10 @@ cas::ondisk::tryLockFileThreadSafe(int FD, std::chrono::milliseconds Timeout,
|
|||
auto Start = std::chrono::steady_clock::now();
|
||||
auto End = Start + Timeout;
|
||||
do {
|
||||
if (flock(FD, (Kind == sys::fs::LockKind::Exclusive ? LOCK_EX : LOCK_SH) |
|
||||
LOCK_NB) == 0)
|
||||
if (sys::RetryAfterSignal(
|
||||
-1, flock, FD,
|
||||
(Kind == sys::fs::LockKind::Exclusive ? LOCK_EX : LOCK_SH) |
|
||||
LOCK_NB) == 0)
|
||||
return std::error_code();
|
||||
int Error = errno;
|
||||
if (Error == EWOULDBLOCK) {
|
||||
|
|
@ -146,7 +151,11 @@ Expected<size_t> cas::ondisk::preallocateFileTail(int FD, size_t CurrentSize,
|
|||
};
|
||||
#if defined(HAVE_POSIX_FALLOCATE)
|
||||
// Note: posix_fallocate returns its error directly, not via errno.
|
||||
if (int Err = posix_fallocate(FD, CurrentSize, NewSize - CurrentSize))
|
||||
int Err;
|
||||
do {
|
||||
Err = posix_fallocate(FD, CurrentSize, NewSize - CurrentSize);
|
||||
} while (Err == EINTR);
|
||||
if (Err)
|
||||
return CreateError(std::error_code(Err, std::generic_category()));
|
||||
return NewSize;
|
||||
#elif defined(__APPLE__)
|
||||
|
|
@ -162,7 +171,7 @@ Expected<size_t> cas::ondisk::preallocateFileTail(int FD, size_t CurrentSize,
|
|||
FAlloc.fst_offset = 0;
|
||||
FAlloc.fst_length = NewSize - CurrentSize;
|
||||
FAlloc.fst_bytesalloc = 0;
|
||||
if (fcntl(FD, F_PREALLOCATE, &FAlloc))
|
||||
if (sys::RetryAfterSignal(-1, ::fcntl, FD, F_PREALLOCATE, &FAlloc) == -1)
|
||||
return CreateError(errnoAsErrorCode());
|
||||
assert(CurrentSize + FAlloc.fst_bytesalloc >= NewSize);
|
||||
return CurrentSize + FAlloc.fst_bytesalloc;
|
||||
|
|
|
|||
|
|
@ -612,7 +612,7 @@ std::error_code rename(const Twine &from, const Twine &to) {
|
|||
std::error_code resize_file(int FD, uint64_t Size) {
|
||||
// Use ftruncate as a fallback. It may or may not allocate space. At least on
|
||||
// OS X with HFS+ it does.
|
||||
if (::ftruncate(FD, Size) == -1)
|
||||
if (sys::RetryAfterSignal(-1, ::ftruncate, FD, Size) == -1)
|
||||
return errnoAsErrorCode();
|
||||
|
||||
return std::error_code();
|
||||
|
|
@ -913,7 +913,7 @@ void mapped_file_region::unmapImpl() {
|
|||
}
|
||||
|
||||
std::error_code mapped_file_region::sync() const {
|
||||
if (int Res = ::msync(Mapping, Size, MS_SYNC))
|
||||
if (int Res = sys::RetryAfterSignal(-1, ::msync, Mapping, Size, MS_SYNC))
|
||||
return std::error_code(Res, std::generic_category());
|
||||
return std::error_code();
|
||||
}
|
||||
|
|
@ -1340,7 +1340,7 @@ std::error_code lockFile(int FD, LockKind Kind) {
|
|||
Lock.l_whence = SEEK_SET;
|
||||
Lock.l_start = 0;
|
||||
Lock.l_len = 0;
|
||||
if (::fcntl(FD, F_SETLKW, &Lock) != -1)
|
||||
if (sys::RetryAfterSignal(-1, ::fcntl, FD, F_SETLKW, &Lock) != -1)
|
||||
return std::error_code();
|
||||
return errnoAsErrorCode();
|
||||
}
|
||||
|
|
@ -1351,7 +1351,7 @@ std::error_code unlockFile(int FD) {
|
|||
Lock.l_whence = SEEK_SET;
|
||||
Lock.l_start = 0;
|
||||
Lock.l_len = 0;
|
||||
if (::fcntl(FD, F_SETLK, &Lock) != -1)
|
||||
if (sys::RetryAfterSignal(-1, ::fcntl, FD, F_SETLK, &Lock) != -1)
|
||||
return std::error_code();
|
||||
return errnoAsErrorCode();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue