2 * Copyright 2013 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "folly/FileUtil.h"
23 int closeNoInt(int fd) {
25 // Ignore EINTR. On Linux, close() may only return EINTR after the file
26 // descriptor has been closed, so you must not retry close() on EINTR --
27 // in the best case, you'll get EBADF, and in the worst case, you'll end up
28 // closing a different file (one opened from another thread).
30 // Interestingly enough, the Single Unix Specification says that the state
31 // of the file descriptor is unspecified if close returns EINTR. In that
32 // case, the safe thing to do is also not to retry close() -- leaking a file
33 // descriptor is probably better than closing the wrong file.
34 if (r == -1 && errno == EINTR) {
42 // Wrap call to f(args) in loop to retry on EINTR
43 template<typename F, typename... Args>
44 ssize_t wrapNoInt(F f, Args... args) {
48 } while (r == -1 && errno == EINTR);
54 ssize_t readNoInt(int fd, void* buf, size_t count) {
55 return wrapNoInt(read, fd, buf, count);
58 ssize_t preadNoInt(int fd, void* buf, size_t count, off_t offset) {
59 return wrapNoInt(pread, fd, buf, count, offset);
62 ssize_t readvNoInt(int fd, const struct iovec* iov, int count) {
63 return wrapNoInt(writev, fd, iov, count);
66 ssize_t writeNoInt(int fd, const void* buf, size_t count) {
67 return wrapNoInt(write, fd, buf, count);
70 ssize_t pwriteNoInt(int fd, const void* buf, size_t count, off_t offset) {
71 return wrapNoInt(pwrite, fd, buf, count, offset);
74 ssize_t writevNoInt(int fd, const struct iovec* iov, int count) {
75 return wrapNoInt(writev, fd, iov, count);
78 ssize_t readFull(int fd, void* buf, size_t count) {
79 char* b = static_cast<char*>(buf);
80 ssize_t totalBytes = 0;
83 r = read(fd, b, count);
94 } while (r != 0 && count); // 0 means EOF
99 ssize_t preadFull(int fd, void* buf, size_t count, off_t offset) {
100 char* b = static_cast<char*>(buf);
101 ssize_t totalBytes = 0;
104 r = pread(fd, b, count, offset);
106 if (errno == EINTR) {
116 } while (r != 0 && count); // 0 means EOF
121 ssize_t writeFull(int fd, const void* buf, size_t count) {
122 const char* b = static_cast<const char*>(buf);
123 ssize_t totalBytes = 0;
126 r = write(fd, b, count);
128 if (errno == EINTR) {
137 } while (r != 0 && count); // 0 means EOF
142 ssize_t pwriteFull(int fd, const void* buf, size_t count, off_t offset) {
143 const char* b = static_cast<const char*>(buf);
144 ssize_t totalBytes = 0;
147 r = pwrite(fd, b, count, offset);
149 if (errno == EINTR) {
159 } while (r != 0 && count); // 0 means EOF