llvm.org GIT mirror llvm / 2dfb7e4
Revert "[Support] Add RetryAfterSignal helper function" and subsequent fix The fix in r306003 uncovered a pretty fundamental problem that libc++ implementation of std::result_of does not handle the prototype of open(2) correctly (presumably because it contains ...). This makes the whole function unusable in its current form, so I am also reverting the original commit (r305892), which introduced the function, at least until I figure out a way to solve the libc++ issue. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306005 91177308-0d34-0410-b5e6-96231b3b80d8 Pavel Labath 2 years ago
6 changed file(s) with 25 addition(s) and 64 deletion(s). Raw diff Collapse all Expand all
1515
1616 #include
1717 #include
18 #include
1918
2019 namespace llvm {
2120 namespace sys {
2928 /// Like the no-argument version above, but uses \p errnum instead of errno.
3029 std::string StrError(int errnum);
3130
32 template
33 typename ResultT = std::result_of>
34 inline typename ResultT::type RetryAfterSignal(typename ResultT::type Fail,
35 const Fun &F,
36 const Args &... As) {
37 typename ResultT::type Res;
38 do
39 Res = F(As...);
40 while (Res == Fail && errno == EINTR);
41 return Res;
42 }
43
4431 } // namespace sys
4532 } // namespace llvm
4633
239239 // Read into Buffer until we hit EOF.
240240 do {
241241 Buffer.reserve(Buffer.size() + ChunkSize);
242 ReadBytes = sys::RetryAfterSignal(-1, read, FD, Buffer.end(), ChunkSize);
243 if (ReadBytes == -1)
242 ReadBytes = read(FD, Buffer.end(), ChunkSize);
243 if (ReadBytes == -1) {
244 if (errno == EINTR) continue;
244245 return std::error_code(errno, std::generic_category());
246 }
245247 Buffer.set_size(Buffer.size() + ReadBytes);
246248 } while (ReadBytes != 0);
247249
388390
389391 while (BytesLeft) {
390392 #ifdef HAVE_PREAD
391 ssize_t NumRead = sys::RetryAfterSignal(-1, ::pread, FD, BufPtr, BytesLeft,
392 MapSize - BytesLeft + Offset);
393 ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
393394 #else
394 ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, BufPtr, BytesLeft);
395 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
395396 #endif
396397 if (NumRead == -1) {
398 if (errno == EINTR)
399 continue;
397400 // Error while reading.
398401 return std::error_code(errno, std::generic_category());
399402 }
736736 #ifdef O_CLOEXEC
737737 OpenFlags |= O_CLOEXEC;
738738 #endif
739 if ((ResultFD = sys::RetryAfterSignal(-1, open, P.begin(), OpenFlags)) < 0)
740 return std::error_code(errno, std::generic_category());
739 while ((ResultFD = open(P.begin(), OpenFlags)) < 0) {
740 if (errno != EINTR)
741 return std::error_code(errno, std::generic_category());
742 }
741743 #ifndef O_CLOEXEC
742744 int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
743745 (void)r;
797799
798800 SmallString<128> Storage;
799801 StringRef P = Name.toNullTerminatedStringRef(Storage);
800 if ((ResultFD = sys::RetryAfterSignal(-1, open, P.begin(), OpenFlags, Mode)) < 0)
801 return std::error_code(errno, std::generic_category());
802 while ((ResultFD = open(P.begin(), OpenFlags, Mode)) < 0) {
803 if (errno != EINTR)
804 return std::error_code(errno, std::generic_category());
805 }
802806 #ifndef O_CLOEXEC
803807 int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
804808 (void)r;
206206 for (int StandardFD : StandardFDs) {
207207 struct stat st;
208208 errno = 0;
209 if (RetryAfterSignal(-1, fstat, StandardFD, &st) < 0) {
209 while (fstat(StandardFD, &st) < 0) {
210210 assert(errno && "expected errno to be set if fstat failed!");
211211 // fstat should return EBADF if the file descriptor is closed.
212 if (errno != EBADF)
212 if (errno == EBADF)
213 break;
214 // retry fstat if we got EINTR, otherwise bubble up the failure.
215 if (errno != EINTR)
213216 return std::error_code(errno, std::generic_category());
214217 }
215218 // if fstat succeeds, move on to the next FD.
218221 assert(errno == EBADF && "expected errno to have EBADF at this point!");
219222
220223 if (NullFD < 0) {
221 if ((NullFD = RetryAfterSignal(-1, open, "/dev/null", O_RDWR)) < 0)
224 while ((NullFD = open("/dev/null", O_RDWR)) < 0) {
225 if (errno == EINTR)
226 continue;
222227 return std::error_code(errno, std::generic_category());
228 }
223229 }
224230
225231 if (NullFD == StandardFD)
2020 DebugTest.cpp
2121 EndianStreamTest.cpp
2222 EndianTest.cpp
23 ErrnoTest.cpp
2423 ErrorOrTest.cpp
2524 ErrorTest.cpp
2625 FileOutputBufferTest.cpp
+0
-38
unittests/Support/ErrnoTest.cpp less more
None //===- ErrnoTest.cpp - Error handling unit tests --------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Support/Errno.h"
10 #include "gtest/gtest.h"
11
12 using namespace llvm::sys;
13
14 static int *ReturnPointer() { return new int(47); }
15
16 TEST(ErrnoTest, RetryAfterSignal) {
17 EXPECT_EQ(1, RetryAfterSignal(-1, [] { return 1; }));
18
19 EXPECT_EQ(-1, RetryAfterSignal(-1, [] {
20 errno = EAGAIN;
21 return -1;
22 }));
23 EXPECT_EQ(EAGAIN, errno);
24
25 unsigned calls = 0;
26 EXPECT_EQ(1, RetryAfterSignal(-1, [&calls] {
27 errno = EINTR;
28 ++calls;
29 return calls == 1 ? -1 : 1;
30 }));
31 EXPECT_EQ(2u, calls);
32
33 EXPECT_EQ(1, RetryAfterSignal(-1, [](int x) { return x; }, 1));
34
35 std::unique_ptr P{RetryAfterSignal(nullptr, ReturnPointer)};
36 EXPECT_EQ(47, *P);
37 }