OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <errno.h> | 5 #include <errno.h> |
6 #include <fcntl.h> | 6 #include <fcntl.h> |
7 #include <unistd.h> | 7 #include <unistd.h> |
8 #include <sys/ioctl.h> | 8 #include <sys/ioctl.h> |
9 | 9 |
10 #include "bin/fdutils.h" | 10 #include "bin/fdutils.h" |
11 | 11 |
12 | 12 |
13 bool FDUtils::SetNonBlocking(intptr_t fd) { | 13 bool FDUtils::SetNonBlocking(intptr_t fd) { |
14 intptr_t status; | 14 intptr_t status; |
15 status = fcntl(fd, F_GETFL); | 15 status = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); |
16 if (status < 0) { | 16 if (status < 0) { |
17 perror("fcntl F_GETFL failed"); | 17 perror("fcntl F_GETFL failed"); |
18 return false; | 18 return false; |
19 } | 19 } |
20 status = (status | O_NONBLOCK); | 20 status = (status | O_NONBLOCK); |
21 if (fcntl(fd, F_SETFL, status) < 0) { | 21 if (TEMP_FAILURE_RETRY(fcntl(fd, F_SETFL, status)) < 0) { |
22 perror("fcntl F_SETFL failed"); | 22 perror("fcntl F_SETFL failed"); |
23 return false; | 23 return false; |
24 } | 24 } |
25 return true; | 25 return true; |
26 } | 26 } |
27 | 27 |
28 | 28 |
29 bool FDUtils::IsBlocking(intptr_t fd, bool* is_blocking) { | 29 bool FDUtils::IsBlocking(intptr_t fd, bool* is_blocking) { |
30 intptr_t status; | 30 intptr_t status; |
31 status = fcntl(fd, F_GETFL); | 31 status = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); |
32 if (status < 0) { | 32 if (status < 0) { |
33 perror("fcntl F_GETFL failed"); | 33 perror("fcntl F_GETFL failed"); |
34 return false; | 34 return false; |
35 } | 35 } |
36 *is_blocking = (status & O_NONBLOCK) == 0; | 36 *is_blocking = (status & O_NONBLOCK) == 0; |
37 return true; | 37 return true; |
38 } | 38 } |
39 | 39 |
40 | 40 |
41 intptr_t FDUtils::AvailableBytes(intptr_t fd) { | 41 intptr_t FDUtils::AvailableBytes(intptr_t fd) { |
42 size_t available; | 42 size_t available; |
43 int result = ioctl(fd, FIONREAD, &available); | 43 int result = TEMP_FAILURE_RETRY(ioctl(fd, FIONREAD, &available)); |
44 if (result < 0) { | 44 if (result < 0) { |
45 return result; | 45 return result; |
46 } | 46 } |
47 return available; | 47 return available; |
48 } | 48 } |
49 | 49 |
50 | 50 |
51 ssize_t FDUtils::ReadFromBlocking(int fd, void* buffer, size_t count) { | 51 ssize_t FDUtils::ReadFromBlocking(int fd, void* buffer, size_t count) { |
52 #ifdef DEBUG | 52 #ifdef DEBUG |
53 bool is_blocking = false; | 53 bool is_blocking = false; |
54 ASSERT(FDUtils::IsBlocking(fd, &is_blocking)); | 54 ASSERT(FDUtils::IsBlocking(fd, &is_blocking)); |
55 ASSERT(is_blocking); | 55 ASSERT(is_blocking); |
56 #endif | 56 #endif |
57 size_t remaining = count; | 57 size_t remaining = count; |
58 char* buffer_pos = reinterpret_cast<char*>(buffer); | 58 char* buffer_pos = reinterpret_cast<char*>(buffer); |
59 while (remaining > 0) { | 59 while (remaining > 0) { |
60 ssize_t bytes_read = read(fd, buffer_pos, remaining); | 60 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer_pos, remaining)); |
61 if (bytes_read == 0) { | 61 if (bytes_read == 0) { |
62 return count - remaining; | 62 return count - remaining; |
63 } else if (bytes_read == -1 && errno != EINTR) { | 63 } else if (bytes_read == -1) { |
64 // Error codes EAGAIN and EWOULDBLOCK should only happen for non | 64 ASSERT(EAGAIN == EWOULDBLOCK); |
65 // blocking file descriptors. | 65 // Error code EWOULDBLOCK should only happen for non blocking |
66 ASSERT(errno != EAGAIN && errno != EWOULDBLOCK); | 66 // file descriptors. |
| 67 ASSERT(errno != EWOULDBLOCK); |
67 return -1; | 68 return -1; |
68 } else if (bytes_read > 0) { | 69 } else { |
| 70 ASSERT((bytes_read > 0)); |
69 remaining -= bytes_read; | 71 remaining -= bytes_read; |
70 buffer_pos += bytes_read; | 72 buffer_pos += bytes_read; |
71 } else { | |
72 ASSERT(errno == EINTR); | |
73 } | 73 } |
74 } | 74 } |
75 return count; | 75 return count; |
76 } | 76 } |
77 | 77 |
78 | 78 |
79 ssize_t FDUtils::WriteToBlocking(int fd, const void* buffer, size_t count) { | 79 ssize_t FDUtils::WriteToBlocking(int fd, const void* buffer, size_t count) { |
80 #ifdef DEBUG | 80 #ifdef DEBUG |
81 bool is_blocking = false; | 81 bool is_blocking = false; |
82 ASSERT(FDUtils::IsBlocking(fd, &is_blocking)); | 82 ASSERT(FDUtils::IsBlocking(fd, &is_blocking)); |
83 ASSERT(is_blocking); | 83 ASSERT(is_blocking); |
84 #endif | 84 #endif |
85 size_t remaining = count; | 85 size_t remaining = count; |
86 char* buffer_pos = const_cast<char*>(reinterpret_cast<const char*>(buffer)); | 86 char* buffer_pos = const_cast<char*>(reinterpret_cast<const char*>(buffer)); |
87 while (remaining > 0) { | 87 while (remaining > 0) { |
88 ssize_t bytes_written = write(fd, buffer_pos, remaining); | 88 ssize_t bytes_written = |
| 89 TEMP_FAILURE_RETRY(write(fd, buffer_pos, remaining)); |
89 if (bytes_written == 0) { | 90 if (bytes_written == 0) { |
90 return count - remaining; | 91 return count - remaining; |
91 } else if (bytes_written == -1 && errno != EINTR) { | 92 } else if (bytes_written == -1) { |
92 // Error codes EAGAIN and EWOULDBLOCK should only happen for non | 93 ASSERT(EAGAIN == EWOULDBLOCK); |
93 // blocking file descriptors. | 94 // Error code EWOULDBLOCK should only happen for non blocking |
94 ASSERT(errno != EAGAIN && errno != EWOULDBLOCK); | 95 // file descriptors. |
| 96 ASSERT(errno != EWOULDBLOCK); |
95 return -1; | 97 return -1; |
96 } else if (bytes_written > 0) { | 98 } else { |
| 99 ASSERT(bytes_written > 0); |
97 remaining -= bytes_written; | 100 remaining -= bytes_written; |
98 buffer_pos += bytes_written; | 101 buffer_pos += bytes_written; |
99 } else { | |
100 ASSERT(errno == EINTR); | |
101 } | 102 } |
102 } | 103 } |
103 return count; | 104 return count; |
104 } | 105 } |
OLD | NEW |