Handle EINTR on all IO operations

There have been spurious FileIOExceptions seen on some Mac OS machines.

R=ager@google.com,whesse@google.com

BUG=
TEST=

Review URL: http://codereview.chromium.org//9139011

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3185 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
sgjesse@google.com 2012-01-11 15:12:27 +00:00
parent dea93d6568
commit 0122a33a76
12 changed files with 367 additions and 308 deletions

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -39,7 +39,10 @@ static bool ListRecursively(const char* dir_name,
static void ComputeFullPath(const char* dir_name,
char* path,
int* path_length) {
char* abs_path = realpath(dir_name, path);
char* abs_path;
do {
abs_path = realpath(dir_name, path);
} while (abs_path == NULL && errno == EINTR);
ASSERT(abs_path != NULL);
*path_length = strlen(path);
size_t written = snprintf(path + *path_length,
@ -128,7 +131,10 @@ static bool ListRecursively(const char* dir_name,
Dart_Port file_port,
Dart_Port done_port,
Dart_Port error_port) {
DIR* dir_pointer = opendir(dir_name);
DIR* dir_pointer;
do {
dir_pointer = opendir(dir_name);
} while (dir_pointer == NULL && errno == EINTR);
if (dir_pointer == NULL) {
PostError(error_port, "Directory listing failed for: ", dir_name, errno);
return false;
@ -146,7 +152,9 @@ static bool ListRecursively(const char* dir_name,
bool listing_error = false;
dirent entry;
dirent* result;
while ((success = readdir_r(dir_pointer, &entry, &result)) == 0 &&
while ((success = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
&entry,
&result))) == 0 &&
result != NULL &&
!listing_error) {
switch (entry.d_type) {
@ -173,7 +181,7 @@ static bool ListRecursively(const char* dir_name,
"%s",
entry.d_name);
ASSERT(written == strlen(entry.d_name));
int lstat_success = lstat(path, &entry_info);
int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info));
if (lstat_success == -1) {
listing_error = true;
PostError(error_port, "Directory listing failed for: ", path, errno);
@ -233,7 +241,7 @@ void Directory::List(const char* dir_name,
Directory::ExistsResult Directory::Exists(const char* dir_name) {
struct stat entry_info;
int lstat_success = lstat(dir_name, &entry_info);
int lstat_success = TEMP_FAILURE_RETRY(lstat(dir_name, &entry_info));
if (lstat_success == 0) {
if ((entry_info.st_mode & S_IFMT) == S_IFDIR) {
return EXISTS;
@ -263,7 +271,7 @@ Directory::ExistsResult Directory::Exists(const char* dir_name) {
bool Directory::Create(const char* dir_name) {
// Create the directory with the permissions specified by the
// process umask.
return (mkdir(dir_name, 0777) == 0);
return (TEMP_FAILURE_RETRY(mkdir(dir_name, 0777)) == 0);
}
@ -287,7 +295,10 @@ int Directory::CreateTemp(const char* const_template,
} else {
snprintf(*path, PATH_MAX, "/tmp/temp_dir1_XXXXXX");
}
char* result = mkdtemp(*path);
char* result;
do {
result = mkdtemp(*path);
} while (result == NULL && errno == EINTR);
if (result == NULL) {
SetOsErrorMessage(os_error_message, os_error_message_len);
free(*path);
@ -299,5 +310,5 @@ int Directory::CreateTemp(const char* const_template,
bool Directory::Delete(const char* dir_name) {
return (rmdir(dir_name) == 0);
return (TEMP_FAILURE_RETRY(rmdir(dir_name)) == 0);
}

View file

@ -55,7 +55,7 @@ EventHandlerImplementation::EventHandlerImplementation() {
socket_map_ = reinterpret_cast<SocketData*>(calloc(socket_map_size_,
sizeof(SocketData)));
ASSERT(socket_map_ != NULL);
result = pipe(interrupt_fds_);
result = TEMP_FAILURE_RETRY(pipe(interrupt_fds_));
if (result != 0) {
FATAL("Pipe creation failed");
}
@ -67,8 +67,8 @@ EventHandlerImplementation::EventHandlerImplementation() {
EventHandlerImplementation::~EventHandlerImplementation() {
free(socket_map_);
close(interrupt_fds_[0]);
close(interrupt_fds_[1]);
TEMP_FAILURE_RETRY(close(interrupt_fds_[0]));
TEMP_FAILURE_RETRY(close(interrupt_fds_[1]));
}
@ -82,7 +82,7 @@ SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) {
} while (fd >= new_socket_map_size);
size_t new_socket_map_bytes = new_socket_map_size * sizeof(SocketData);
socket_map_ = reinterpret_cast<SocketData*>(realloc(socket_map_,
new_socket_map_bytes));
new_socket_map_bytes));
ASSERT(socket_map_ != NULL);
size_t socket_map_bytes = socket_map_size_ * sizeof(SocketData);
memset(socket_map_ + socket_map_size_,
@ -147,15 +147,16 @@ struct pollfd* EventHandlerImplementation::GetPollFds(intptr_t* pollfds_size) {
bool EventHandlerImplementation::GetInterruptMessage(InterruptMessage* msg) {
int total_read = 0;
int bytes_read = read(interrupt_fds_[0], msg, kInterruptMessageSize);
int bytes_read =
TEMP_FAILURE_RETRY(read(interrupt_fds_[0], msg, kInterruptMessageSize));
if (bytes_read < 0) {
return false;
}
total_read = bytes_read;
while (total_read < kInterruptMessageSize) {
bytes_read = read(interrupt_fds_[0],
msg + total_read,
kInterruptMessageSize - total_read);
bytes_read = TEMP_FAILURE_RETRY(read(interrupt_fds_[0],
msg + total_read,
kInterruptMessageSize - total_read));
if (bytes_read > 0) {
total_read = total_read + bytes_read;
}
@ -255,11 +256,13 @@ intptr_t EventHandlerImplementation::GetPollEvents(struct pollfd* pollfd) {
// recv to peek for whether the other end of the socket
// actually closed.
char buffer;
ssize_t bytesPeeked = recv(sd->fd(), &buffer, 1, MSG_PEEK);
ssize_t bytesPeeked =
TEMP_FAILURE_RETRY(recv(sd->fd(), &buffer, 1, MSG_PEEK));
ASSERT(EAGAIN == EWOULDBLOCK);
if (bytesPeeked == 0) {
event_mask = (1 << kCloseEvent);
sd->MarkClosedRead();
} else if (errno != EAGAIN) {
} else if (errno != EWOULDBLOCK) {
fprintf(stderr, "Error recv: %s\n", strerror(errno));
}
}
@ -346,9 +349,10 @@ void* EventHandlerImplementation::Poll(void* args) {
while (1) {
pollfds = handler->GetPollFds(&pollfds_size);
intptr_t millis = handler->GetTimeout();
intptr_t result = poll(pollfds, pollfds_size, millis);
intptr_t result = TEMP_FAILURE_RETRY(poll(pollfds, pollfds_size, millis));
ASSERT(EAGAIN == EWOULDBLOCK);
if (result == -1) {
if (errno != EAGAIN && errno != EINTR) {
if (errno != EWOULDBLOCK) {
perror("Poll failed");
}
} else {

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -55,7 +55,7 @@ EventHandlerImplementation::EventHandlerImplementation() {
socket_map_ = reinterpret_cast<SocketData*>(calloc(socket_map_size_,
sizeof(SocketData)));
ASSERT(socket_map_ != NULL);
result = pipe(interrupt_fds_);
result = TEMP_FAILURE_RETRY(pipe(interrupt_fds_));
if (result != 0) {
FATAL("Pipe creation failed");
}
@ -67,8 +67,8 @@ EventHandlerImplementation::EventHandlerImplementation() {
EventHandlerImplementation::~EventHandlerImplementation() {
free(socket_map_);
close(interrupt_fds_[0]);
close(interrupt_fds_[1]);
TEMP_FAILURE_RETRY(close(interrupt_fds_[0]));
TEMP_FAILURE_RETRY(close(interrupt_fds_[1]));
}
@ -82,7 +82,7 @@ SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) {
} while (fd >= new_socket_map_size);
size_t new_socket_map_bytes = new_socket_map_size * sizeof(SocketData);
socket_map_ = reinterpret_cast<SocketData*>(realloc(socket_map_,
new_socket_map_bytes));
new_socket_map_bytes));
ASSERT(socket_map_ != NULL);
size_t socket_map_bytes = socket_map_size_ * sizeof(SocketData);
memset(socket_map_ + socket_map_size_,
@ -147,15 +147,16 @@ struct pollfd* EventHandlerImplementation::GetPollFds(intptr_t* pollfds_size) {
bool EventHandlerImplementation::GetInterruptMessage(InterruptMessage* msg) {
int total_read = 0;
int bytes_read = read(interrupt_fds_[0], msg, kInterruptMessageSize);
int bytes_read =
TEMP_FAILURE_RETRY(read(interrupt_fds_[0], msg, kInterruptMessageSize));
if (bytes_read < 0) {
return false;
}
total_read = bytes_read;
while (total_read < kInterruptMessageSize) {
bytes_read = read(interrupt_fds_[0],
msg + total_read,
kInterruptMessageSize - total_read);
bytes_read = TEMP_FAILURE_RETRY(read(interrupt_fds_[0],
msg + total_read,
kInterruptMessageSize - total_read));
if (bytes_read > 0) {
total_read = total_read + bytes_read;
}
@ -253,11 +254,13 @@ intptr_t EventHandlerImplementation::GetPollEvents(struct pollfd* pollfd) {
// recv to peek for whether the other end of the socket
// actually closed.
char buffer;
ssize_t bytesPeeked = recv(sd->fd(), &buffer, 1, MSG_PEEK);
ssize_t bytesPeeked =
TEMP_FAILURE_RETRY(recv(sd->fd(), &buffer, 1, MSG_PEEK));
ASSERT(EAGAIN == EWOULDBLOCK);
if (bytesPeeked == 0) {
event_mask = (1 << kCloseEvent);
sd->MarkClosedRead();
} else if (errno != EAGAIN) {
} else if (errno != EWOULDBLOCK) {
fprintf(stderr, "Error recv: %s\n", strerror(errno));
}
}
@ -344,9 +347,10 @@ void* EventHandlerImplementation::Poll(void* args) {
while (1) {
pollfds = handler->GetPollFds(&pollfds_size);
intptr_t millis = handler->GetTimeout();
intptr_t result = poll(pollfds, pollfds_size, millis);
intptr_t result = TEMP_FAILURE_RETRY(poll(pollfds, pollfds_size, millis));
ASSERT(EAGAIN == EWOULDBLOCK);
if (result == -1) {
if (errno != EAGAIN && errno != EINTR) {
if (errno != EWOULDBLOCK) {
perror("Poll failed");
}
} else {

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -12,13 +12,13 @@
bool FDUtils::SetNonBlocking(intptr_t fd) {
intptr_t status;
status = fcntl(fd, F_GETFL);
status = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
if (status < 0) {
perror("fcntl F_GETFL failed");
return false;
}
status = (status | O_NONBLOCK);
if (fcntl(fd, F_SETFL, status) < 0) {
if (TEMP_FAILURE_RETRY(fcntl(fd, F_SETFL, status)) < 0) {
perror("fcntl F_SETFL failed");
return false;
}
@ -28,7 +28,7 @@ bool FDUtils::SetNonBlocking(intptr_t fd) {
bool FDUtils::IsBlocking(intptr_t fd, bool* is_blocking) {
intptr_t status;
status = fcntl(fd, F_GETFL);
status = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
if (status < 0) {
perror("fcntl F_GETFL failed");
return false;
@ -40,7 +40,7 @@ bool FDUtils::IsBlocking(intptr_t fd, bool* is_blocking) {
intptr_t FDUtils::AvailableBytes(intptr_t fd) {
size_t available;
int result = ioctl(fd, FIONREAD, &available);
int result = TEMP_FAILURE_RETRY(ioctl(fd, FIONREAD, &available));
if (result < 0) {
return result;
}
@ -57,19 +57,19 @@ ssize_t FDUtils::ReadFromBlocking(int fd, void* buffer, size_t count) {
size_t remaining = count;
char* buffer_pos = reinterpret_cast<char*>(buffer);
while (remaining > 0) {
ssize_t bytes_read = read(fd, buffer_pos, remaining);
ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer_pos, remaining));
if (bytes_read == 0) {
return count - remaining;
} else if (bytes_read == -1 && errno != EINTR) {
// Error codes EAGAIN and EWOULDBLOCK should only happen for non
// blocking file descriptors.
ASSERT(errno != EAGAIN && errno != EWOULDBLOCK);
} else if (bytes_read == -1) {
ASSERT(EAGAIN == EWOULDBLOCK);
// Error code EWOULDBLOCK should only happen for non blocking
// file descriptors.
ASSERT(errno != EWOULDBLOCK);
return -1;
} else if (bytes_read > 0) {
} else {
ASSERT((bytes_read > 0));
remaining -= bytes_read;
buffer_pos += bytes_read;
} else {
ASSERT(errno == EINTR);
}
}
return count;
@ -85,19 +85,20 @@ ssize_t FDUtils::WriteToBlocking(int fd, const void* buffer, size_t count) {
size_t remaining = count;
char* buffer_pos = const_cast<char*>(reinterpret_cast<const char*>(buffer));
while (remaining > 0) {
ssize_t bytes_written = write(fd, buffer_pos, remaining);
ssize_t bytes_written =
TEMP_FAILURE_RETRY(write(fd, buffer_pos, remaining));
if (bytes_written == 0) {
return count - remaining;
} else if (bytes_written == -1 && errno != EINTR) {
// Error codes EAGAIN and EWOULDBLOCK should only happen for non
// blocking file descriptors.
ASSERT(errno != EAGAIN && errno != EWOULDBLOCK);
} else if (bytes_written == -1) {
ASSERT(EAGAIN == EWOULDBLOCK);
// Error code EWOULDBLOCK should only happen for non blocking
// file descriptors.
ASSERT(errno != EWOULDBLOCK);
return -1;
} else if (bytes_written > 0) {
} else {
ASSERT(bytes_written > 0);
remaining -= bytes_written;
buffer_pos += bytes_written;
} else {
ASSERT(errno == EINTR);
}
}
return count;

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -12,13 +12,13 @@
bool FDUtils::SetNonBlocking(intptr_t fd) {
intptr_t status;
status = fcntl(fd, F_GETFL);
status = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
if (status < 0) {
perror("fcntl F_GETFL failed");
return false;
}
status = (status | O_NONBLOCK);
if (fcntl(fd, F_SETFL, status) < 0) {
if (TEMP_FAILURE_RETRY(fcntl(fd, F_SETFL, status)) < 0) {
perror("fcntl F_SETFL failed");
return false;
}
@ -28,7 +28,7 @@ bool FDUtils::SetNonBlocking(intptr_t fd) {
bool FDUtils::IsBlocking(intptr_t fd, bool* is_blocking) {
intptr_t status;
status = fcntl(fd, F_GETFL);
status = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
if (status < 0) {
perror("fcntl F_GETFL failed");
return false;
@ -40,7 +40,7 @@ bool FDUtils::IsBlocking(intptr_t fd, bool* is_blocking) {
intptr_t FDUtils::AvailableBytes(intptr_t fd) {
size_t available;
int result = ioctl(fd, FIONREAD, &available);
int result = TEMP_FAILURE_RETRY(ioctl(fd, FIONREAD, &available));
if (result < 0) {
return result;
}
@ -57,19 +57,19 @@ ssize_t FDUtils::ReadFromBlocking(int fd, void* buffer, size_t count) {
size_t remaining = count;
char* buffer_pos = reinterpret_cast<char*>(buffer);
while (remaining > 0) {
ssize_t bytes_read = read(fd, buffer_pos, remaining);
ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer_pos, remaining));
if (bytes_read == 0) {
return count - remaining;
} else if (bytes_read == -1 && errno != EINTR) {
// Error codes EAGAIN and EWOULDBLOCK should only happen for non
// blocking file descriptors.
ASSERT(errno != EAGAIN && errno != EWOULDBLOCK);
} else if (bytes_read == -1) {
ASSERT(EAGAIN == EWOULDBLOCK);
// Error code EWOULDBLOCK should only happen for non blocking
// file descriptors.
ASSERT(errno != EWOULDBLOCK);
return -1;
} else if (bytes_read > 0) {
} else {
ASSERT((bytes_read > 0));
remaining -= bytes_read;
buffer_pos += bytes_read;
} else {
ASSERT(errno == EINTR);
}
}
return count;
@ -85,19 +85,20 @@ ssize_t FDUtils::WriteToBlocking(int fd, const void* buffer, size_t count) {
size_t remaining = count;
char* buffer_pos = const_cast<char*>(reinterpret_cast<const char*>(buffer));
while (remaining > 0) {
ssize_t bytes_written = write(fd, buffer_pos, remaining);
ssize_t bytes_written =
TEMP_FAILURE_RETRY(write(fd, buffer_pos, remaining));
if (bytes_written == 0) {
return count - remaining;
} else if (bytes_written == -1 && errno != EINTR) {
// Error codes EAGAIN and EWOULDBLOCK should only happen for non
// blocking file descriptors.
ASSERT(errno != EAGAIN && errno != EWOULDBLOCK);
} else if (bytes_written == -1) {
ASSERT(EAGAIN == EWOULDBLOCK);
// Error code EWOULDBLOCK should only happen for non blocking
// file descriptors.
ASSERT(errno != EWOULDBLOCK);
return -1;
} else if (bytes_written > 0) {
} else {
ASSERT(bytes_written > 0);
remaining -= bytes_written;
buffer_pos += bytes_written;
} else {
ASSERT(errno == EINTR);
}
}
return count;

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -38,7 +38,7 @@ File::~File() {
void File::Close() {
ASSERT(handle_->fd() >= 0);
int err = close(handle_->fd());
int err = TEMP_FAILURE_RETRY(close(handle_->fd()));
if (err != 0) {
const int kBufferSize = 1024;
char error_message[kBufferSize];
@ -56,49 +56,49 @@ bool File::IsClosed() {
int64_t File::Read(void* buffer, int64_t num_bytes) {
ASSERT(handle_->fd() >= 0);
return read(handle_->fd(), buffer, num_bytes);
return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes));
}
int64_t File::Write(const void* buffer, int64_t num_bytes) {
ASSERT(handle_->fd() >= 0);
return write(handle_->fd(), buffer, num_bytes);
return TEMP_FAILURE_RETRY(write(handle_->fd(), buffer, num_bytes));
}
off_t File::Position() {
ASSERT(handle_->fd() >= 0);
return lseek(handle_->fd(), 0, SEEK_CUR);
return TEMP_FAILURE_RETRY(lseek(handle_->fd(), 0, SEEK_CUR));
}
bool File::SetPosition(int64_t position) {
ASSERT(handle_->fd() >= 0);
return (lseek(handle_->fd(), position, SEEK_SET) != -1);
return TEMP_FAILURE_RETRY(lseek(handle_->fd(), position, SEEK_SET) != -1);
}
bool File::Truncate(int64_t length) {
ASSERT(handle_->fd() >= 0);
return (ftruncate(handle_->fd(), length) != -1);
return TEMP_FAILURE_RETRY(ftruncate(handle_->fd(), length) != -1);
}
void File::Flush() {
ASSERT(handle_->fd() >= 0);
fsync(handle_->fd());
TEMP_FAILURE_RETRY(fsync(handle_->fd()));
}
off_t File::Length() {
ASSERT(handle_->fd() >= 0);
off_t position = lseek(handle_->fd(), 0, SEEK_CUR);
off_t position = TEMP_FAILURE_RETRY(lseek(handle_->fd(), 0, SEEK_CUR));
if (position < 0) {
// The file is not capable of seeking. Return an error.
return -1;
}
off_t result = lseek(handle_->fd(), 0, SEEK_END);
lseek(handle_->fd(), position, SEEK_SET);
off_t result = TEMP_FAILURE_RETRY(lseek(handle_->fd(), 0, SEEK_END));
TEMP_FAILURE_RETRY(lseek(handle_->fd(), position, SEEK_SET));
return result;
}
@ -111,7 +111,7 @@ File* File::Open(const char* name, FileOpenMode mode) {
if ((mode & kTruncate) != 0) {
flags = flags | O_TRUNC;
}
int fd = open(name, flags, 0666);
int fd = TEMP_FAILURE_RETRY(open(name, flags, 0666));
if (fd < 0) {
return NULL;
}
@ -121,7 +121,7 @@ File* File::Open(const char* name, FileOpenMode mode) {
bool File::Exists(const char* name) {
struct stat st;
if (stat(name, &st) == 0) {
if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
return S_ISREG(st.st_mode); // Deal with symlinks?
} else {
return false;
@ -130,7 +130,7 @@ bool File::Exists(const char* name) {
bool File::Create(const char* name) {
int fd = open(name, O_RDONLY | O_CREAT, 0666);
int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CREAT, 0666));
if (fd < 0) {
return false;
}
@ -139,7 +139,7 @@ bool File::Create(const char* name) {
bool File::Delete(const char* name) {
int status = remove(name);
int status = TEMP_FAILURE_RETRY(remove(name));
if (status == -1) {
return false;
}
@ -155,7 +155,9 @@ bool File::IsAbsolutePath(const char* pathname) {
char* File::GetCanonicalPath(const char* pathname) {
char* abs_path = NULL;
if (pathname != NULL) {
abs_path = realpath(pathname, NULL);
do {
abs_path = realpath(pathname, NULL);
} while (abs_path == NULL && errno == EINTR);
assert(abs_path == NULL || IsAbsolutePath(abs_path));
}
return abs_path;

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -39,7 +39,7 @@ File::~File() {
void File::Close() {
ASSERT(handle_->fd() >= 0);
int err = close(handle_->fd());
int err = TEMP_FAILURE_RETRY(close(handle_->fd()));
if (err != 0) {
const int kBufferSize = 1024;
char error_message[kBufferSize];
@ -57,49 +57,49 @@ bool File::IsClosed() {
int64_t File::Read(void* buffer, int64_t num_bytes) {
ASSERT(handle_->fd() >= 0);
return read(handle_->fd(), buffer, num_bytes);
return TEMP_FAILURE_RETRY(read(handle_->fd(), buffer, num_bytes));
}
int64_t File::Write(const void* buffer, int64_t num_bytes) {
ASSERT(handle_->fd() >= 0);
return write(handle_->fd(), buffer, num_bytes);
return TEMP_FAILURE_RETRY(write(handle_->fd(), buffer, num_bytes));
}
off_t File::Position() {
ASSERT(handle_->fd() >= 0);
return lseek(handle_->fd(), 0, SEEK_CUR);
return TEMP_FAILURE_RETRY(lseek(handle_->fd(), 0, SEEK_CUR));
}
bool File::SetPosition(int64_t position) {
ASSERT(handle_->fd() >= 0);
return (lseek(handle_->fd(), position, SEEK_SET) != -1);
return TEMP_FAILURE_RETRY(lseek(handle_->fd(), position, SEEK_SET) != -1);
}
bool File::Truncate(int64_t length) {
ASSERT(handle_->fd() >= 0);
return (ftruncate(handle_->fd(), length) != -1);
return TEMP_FAILURE_RETRY(ftruncate(handle_->fd(), length) != -1);
}
void File::Flush() {
ASSERT(handle_->fd() >= 0);
fsync(handle_->fd());
TEMP_FAILURE_RETRY(fsync(handle_->fd()));
}
off_t File::Length() {
ASSERT(handle_->fd() >= 0);
off_t position = lseek(handle_->fd(), 0, SEEK_CUR);
off_t position = TEMP_FAILURE_RETRY(lseek(handle_->fd(), 0, SEEK_CUR));
if (position < 0) {
// The file is not capable of seeking. Return an error.
return -1;
}
off_t result = lseek(handle_->fd(), 0, SEEK_END);
lseek(handle_->fd(), position, SEEK_SET);
off_t result = TEMP_FAILURE_RETRY(lseek(handle_->fd(), 0, SEEK_END));
TEMP_FAILURE_RETRY(lseek(handle_->fd(), position, SEEK_SET));
return result;
}
@ -112,7 +112,7 @@ File* File::Open(const char* name, FileOpenMode mode) {
if ((mode & kTruncate) != 0) {
flags = flags | O_TRUNC;
}
int fd = open(name, flags, 0666);
int fd = TEMP_FAILURE_RETRY(open(name, flags, 0666));
if (fd < 0) {
return NULL;
}
@ -122,7 +122,7 @@ File* File::Open(const char* name, FileOpenMode mode) {
bool File::Exists(const char* name) {
struct stat st;
if (stat(name, &st) == 0) {
if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
return S_ISREG(st.st_mode); // Deal with symlinks?
} else {
return false;
@ -130,13 +130,8 @@ bool File::Exists(const char* name) {
}
bool File::IsAbsolutePath(const char* pathname) {
return (pathname != NULL && pathname[0] == '/');
}
bool File::Create(const char* name) {
int fd = open(name, O_RDONLY | O_CREAT, 0666);
int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CREAT, 0666));
if (fd < 0) {
return false;
}
@ -145,7 +140,7 @@ bool File::Create(const char* name) {
bool File::Delete(const char* name) {
int status = remove(name);
int status = TEMP_FAILURE_RETRY(remove(name));
if (status == -1) {
return false;
}
@ -153,6 +148,11 @@ bool File::Delete(const char* name) {
}
bool File::IsAbsolutePath(const char* pathname) {
return (pathname != NULL && pathname[0] == '/');
}
char* File::GetCanonicalPath(const char* pathname) {
char* abs_path = NULL;
if (pathname != NULL) {
@ -160,9 +160,11 @@ char* File::GetCanonicalPath(const char* pathname) {
// space for the resolved_path when a NULL is passed in does not seem to
// work, so we explicitly allocate space. The caller is responsible for
// freeing this space as in a regular realpath call.
char* resolved_path = reinterpret_cast<char*>(malloc(PATH_MAX+1));
char* resolved_path = reinterpret_cast<char*>(malloc(PATH_MAX + 1));
ASSERT(resolved_path != NULL);
abs_path = realpath(pathname, resolved_path);
do {
abs_path = realpath(pathname, NULL);
} while (abs_path == NULL && errno == EINTR);
assert(abs_path == NULL || IsAbsolutePath(abs_path));
}
return abs_path;

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -88,7 +88,7 @@ static void SetChildOsErrorMessage(char* os_error_message,
void ExitHandler(int process_signal, siginfo_t* siginfo, void* tmp) {
int pid = 0;
int status = 0;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
while ((pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) {
int exit_code = 0;
int negative = 0;
if (WIFEXITED(status)) {
@ -106,7 +106,7 @@ void ExitHandler(int process_signal, siginfo_t* siginfo, void* tmp) {
if (result != sizeof(message) && errno != EPIPE) {
perror("ExitHandler notification failed");
}
close(process->fd());
TEMP_FAILURE_RETRY(close(process->fd()));
}
}
}
@ -125,7 +125,7 @@ static void ReportChildError(int exec_control_fd) {
FDUtils::WriteToBlocking(
exec_control_fd, os_error_message, strlen(os_error_message) + 1);
}
close(exec_control_fd);
TEMP_FAILURE_RETRY(close(exec_control_fd));
exit(1);
}
@ -148,59 +148,61 @@ int Process::Start(const char* path,
int exec_control[2]; // Pipe to get the result from exec.
int result;
result = pipe(read_in);
result = TEMP_FAILURE_RETRY(pipe(read_in));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
result = pipe(read_err);
result = TEMP_FAILURE_RETRY(pipe(read_err));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
result = pipe(write_out);
result = TEMP_FAILURE_RETRY(pipe(write_out));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
result = pipe(exec_control);
result = TEMP_FAILURE_RETRY(pipe(exec_control));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
// Set close on exec on the write file descriptor of the exec control pipe.
result = fcntl(
exec_control[1], F_SETFD, fcntl(exec_control[1], F_GETFD) | FD_CLOEXEC);
result = TEMP_FAILURE_RETRY(
fcntl(exec_control[1],
F_SETFD,
TEMP_FAILURE_RETRY(fcntl(exec_control[1], F_GETFD)) | FD_CLOEXEC));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
close(exec_control[0]);
close(exec_control[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
TEMP_FAILURE_RETRY(close(exec_control[0]));
TEMP_FAILURE_RETRY(close(exec_control[1]));
fprintf(stderr, "fcntl failed: %s\n", os_error_message);
return errno;
}
@ -219,18 +221,18 @@ int Process::Start(const char* path,
if (sigaction(SIGCHLD, &act, 0) != 0) {
perror("Process start: setting signal handler failed");
}
pid = fork();
pid = TEMP_FAILURE_RETRY(fork());
if (pid < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
delete[] program_arguments;
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
close(exec_control[0]);
close(exec_control[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
TEMP_FAILURE_RETRY(close(exec_control[0]));
TEMP_FAILURE_RETRY(close(exec_control[1]));
return errno;
} else if (pid == 0) {
// Wait for parent process before setting up the child process.
@ -241,31 +243,33 @@ int Process::Start(const char* path,
exit(1);
}
close(write_out[1]);
close(read_in[0]);
close(read_err[0]);
close(exec_control[0]);
TEMP_FAILURE_RETRY(close(write_out[1]));
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(exec_control[0]));
if (dup2(write_out[0], STDIN_FILENO) == -1) {
if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) {
ReportChildError(exec_control[1]);
}
close(write_out[0]);
TEMP_FAILURE_RETRY(close(write_out[0]));
if (dup2(read_in[1], STDOUT_FILENO) == -1) {
if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) {
ReportChildError(exec_control[1]);
}
close(read_in[1]);
TEMP_FAILURE_RETRY(close(read_in[1]));
if (dup2(read_err[1], STDERR_FILENO) == -1) {
if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) {
ReportChildError(exec_control[1]);
}
close(read_err[1]);
TEMP_FAILURE_RETRY(close(read_err[1]));
if (working_directory != NULL && chdir(working_directory) == -1) {
if (working_directory != NULL &&
TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) {
ReportChildError(exec_control[1]);
}
execvp(path, const_cast<char* const*>(program_arguments));
TEMP_FAILURE_RETRY(
execvp(path, const_cast<char* const*>(program_arguments)));
ReportChildError(exec_control[1]);
}
@ -273,15 +277,15 @@ int Process::Start(const char* path,
delete[] program_arguments;
int event_fds[2];
result = pipe(event_fds);
result = TEMP_FAILURE_RETRY(pipe(event_fds));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
@ -301,7 +305,7 @@ int Process::Start(const char* path,
// Read exec result from child. If no data is returned the exec was
// successful and the exec call closed the pipe. Otherwise the errno
// is written to the pipe.
close(exec_control[1]);
TEMP_FAILURE_RETRY(close(exec_control[1]));
int child_errno;
int bytes_read = -1;
ASSERT(sizeof(child_errno) == sizeof(errno));
@ -314,16 +318,16 @@ int Process::Start(const char* path,
os_error_message_len);
os_error_message[os_error_message_len - 1] = '\0';
}
close(exec_control[0]);
TEMP_FAILURE_RETRY(close(exec_control[0]));
// Return error code if any failures.
if (bytes_read != 0) {
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
if (bytes_read == -1) {
return errno; // Read failed.
} else {
@ -333,13 +337,13 @@ int Process::Start(const char* path,
FDUtils::SetNonBlocking(read_in[0]);
*in = read_in[0];
close(read_in[1]);
TEMP_FAILURE_RETRY(close(read_in[1]));
FDUtils::SetNonBlocking(write_out[1]);
*out = write_out[1];
close(write_out[0]);
TEMP_FAILURE_RETRY(close(write_out[0]));
FDUtils::SetNonBlocking(read_err[0]);
*err = read_err[0];
close(read_err[1]);
TEMP_FAILURE_RETRY(close(read_err[1]));
*id = pid;
return 0;
@ -347,7 +351,7 @@ int Process::Start(const char* path,
bool Process::Kill(intptr_t id) {
int result = kill(id, SIGKILL);
int result = TEMP_FAILURE_RETRY(kill(id, SIGKILL));
if (result == -1) {
return false;
}

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -87,7 +87,7 @@ static void SetChildOsErrorMessage(char* os_error_message,
void ExitHandler(int process_signal, siginfo_t* siginfo, void* tmp) {
int pid = 0;
int status = 0;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
while ((pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG))) > 0) {
int exit_code = 0;
int negative = 0;
if (WIFEXITED(status)) {
@ -105,7 +105,7 @@ void ExitHandler(int process_signal, siginfo_t* siginfo, void* tmp) {
if (result != sizeof(message) && errno != EPIPE) {
perror("ExitHandler notification failed");
}
close(process->fd());
TEMP_FAILURE_RETRY(close(process->fd()));
}
}
}
@ -124,7 +124,7 @@ static void ReportChildError(int exec_control_fd) {
FDUtils::WriteToBlocking(
exec_control_fd, os_error_message, strlen(os_error_message) + 1);
}
close(exec_control_fd);
TEMP_FAILURE_RETRY(close(exec_control_fd));
exit(1);
}
@ -147,59 +147,61 @@ int Process::Start(const char* path,
int exec_control[2]; // Pipe to get the result from exec.
int result;
result = pipe(read_in);
result = TEMP_FAILURE_RETRY(pipe(read_in));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
result = pipe(read_err);
result = TEMP_FAILURE_RETRY(pipe(read_err));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
result = pipe(write_out);
result = TEMP_FAILURE_RETRY(pipe(write_out));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
result = pipe(exec_control);
result = TEMP_FAILURE_RETRY(pipe(exec_control));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
// Set close on exec on the write file descriptor of the exec control pipe.
result = fcntl(
exec_control[1], F_SETFD, fcntl(exec_control[1], F_GETFD) | FD_CLOEXEC);
result = TEMP_FAILURE_RETRY(
fcntl(exec_control[1],
F_SETFD,
TEMP_FAILURE_RETRY(fcntl(exec_control[1], F_GETFD)) | FD_CLOEXEC));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
close(exec_control[0]);
close(exec_control[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
TEMP_FAILURE_RETRY(close(exec_control[0]));
TEMP_FAILURE_RETRY(close(exec_control[1]));
fprintf(stderr, "fcntl failed: %s\n", os_error_message);
return errno;
}
@ -218,18 +220,18 @@ int Process::Start(const char* path,
if (sigaction(SIGCHLD, &act, 0) != 0) {
perror("Process start: setting signal handler failed");
}
pid = fork();
pid = TEMP_FAILURE_RETRY(fork());
if (pid < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
delete[] program_arguments;
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
close(exec_control[0]);
close(exec_control[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
TEMP_FAILURE_RETRY(close(exec_control[0]));
TEMP_FAILURE_RETRY(close(exec_control[1]));
return errno;
} else if (pid == 0) {
// Wait for parent process before setting up the child process.
@ -240,31 +242,33 @@ int Process::Start(const char* path,
exit(1);
}
close(write_out[1]);
close(read_in[0]);
close(read_err[0]);
close(exec_control[0]);
TEMP_FAILURE_RETRY(close(write_out[1]));
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(exec_control[0]));
if (dup2(write_out[0], STDIN_FILENO) == -1) {
if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) {
ReportChildError(exec_control[1]);
}
close(write_out[0]);
TEMP_FAILURE_RETRY(close(write_out[0]));
if (dup2(read_in[1], STDOUT_FILENO) == -1) {
if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) {
ReportChildError(exec_control[1]);
}
close(read_in[1]);
TEMP_FAILURE_RETRY(close(read_in[1]));
if (dup2(read_err[1], STDERR_FILENO) == -1) {
if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) {
ReportChildError(exec_control[1]);
}
close(read_err[1]);
TEMP_FAILURE_RETRY(close(read_err[1]));
if (working_directory != NULL && chdir(working_directory) == -1) {
if (working_directory != NULL &&
TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) {
ReportChildError(exec_control[1]);
}
execvp(path, const_cast<char* const*>(program_arguments));
TEMP_FAILURE_RETRY(
execvp(path, const_cast<char* const*>(program_arguments)));
ReportChildError(exec_control[1]);
}
@ -272,15 +276,15 @@ int Process::Start(const char* path,
delete[] program_arguments;
int event_fds[2];
result = pipe(event_fds);
result = TEMP_FAILURE_RETRY(pipe(event_fds));
if (result < 0) {
SetChildOsErrorMessage(os_error_message, os_error_message_len);
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
return errno;
}
@ -300,7 +304,7 @@ int Process::Start(const char* path,
// Read exec result from child. If no data is returned the exec was
// successful and the exec call closed the pipe. Otherwise the errno
// is written to the pipe.
close(exec_control[1]);
TEMP_FAILURE_RETRY(close(exec_control[1]));
int child_errno;
int bytes_read = -1;
ASSERT(sizeof(child_errno) == sizeof(errno));
@ -313,16 +317,16 @@ int Process::Start(const char* path,
os_error_message_len);
os_error_message[os_error_message_len - 1] = '\0';
}
close(exec_control[0]);
TEMP_FAILURE_RETRY(close(exec_control[0]));
// Return error code if any failures.
if (bytes_read != 0) {
close(read_in[0]);
close(read_in[1]);
close(read_err[0]);
close(read_err[1]);
close(write_out[0]);
close(write_out[1]);
TEMP_FAILURE_RETRY(close(read_in[0]));
TEMP_FAILURE_RETRY(close(read_in[1]));
TEMP_FAILURE_RETRY(close(read_err[0]));
TEMP_FAILURE_RETRY(close(read_err[1]));
TEMP_FAILURE_RETRY(close(write_out[0]));
TEMP_FAILURE_RETRY(close(write_out[1]));
if (bytes_read == -1) {
return errno; // Read failed.
} else {
@ -332,13 +336,13 @@ int Process::Start(const char* path,
FDUtils::SetNonBlocking(read_in[0]);
*in = read_in[0];
close(read_in[1]);
TEMP_FAILURE_RETRY(close(read_in[1]));
FDUtils::SetNonBlocking(write_out[1]);
*out = write_out[1];
close(write_out[0]);
TEMP_FAILURE_RETRY(close(write_out[0]));
FDUtils::SetNonBlocking(read_err[0]);
*err = read_err[0];
close(read_err[1]);
TEMP_FAILURE_RETRY(close(read_err[1]));
*id = pid;
return 0;
@ -346,7 +350,7 @@ int Process::Start(const char* path,
bool Process::Kill(intptr_t id) {
int result = kill(id, SIGKILL);
int result = TEMP_FAILURE_RETRY(kill(id, SIGKILL));
if (result == -1) {
return false;
}

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -26,7 +26,7 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
struct hostent* server;
struct sockaddr_in server_address;
fd = socket(AF_INET, SOCK_STREAM, 0);
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
if (fd < 0) {
fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
return -1;
@ -36,7 +36,7 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
server = gethostbyname(host);
if (server == NULL) {
close(fd);
TEMP_FAILURE_RETRY(close(fd));
fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
return -1;
}
@ -45,9 +45,10 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
server_address.sin_port = htons(port);
bcopy(server->h_addr, &server_address.sin_addr.s_addr, server->h_length);
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
intptr_t result = connect(fd,
reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address));
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd,
reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address)));
if (result == 0 || errno == EINPROGRESS) {
return fd;
}
@ -62,11 +63,11 @@ intptr_t Socket::Available(intptr_t fd) {
int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
ASSERT(fd >= 0);
ssize_t read_bytes = read(fd, buffer, num_bytes);
if (read_bytes == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) {
// If the read was interrupted or the read would block we need
// to retry and therefore return 0 as the number of bytes written.
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if (read_bytes == -1 && errno == EWOULDBLOCK) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
}
return read_bytes;
@ -75,11 +76,11 @@ int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
ASSERT(fd >= 0);
ssize_t written_bytes = write(fd, buffer, num_bytes);
if (written_bytes == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) {
// If the write was interrupted or the write would block we need
// to retry and therefore return 0 as the number of bytes written.
ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if (written_bytes == -1 && errno == EWOULDBLOCK) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
}
return written_bytes;
@ -90,8 +91,10 @@ intptr_t Socket::GetPort(intptr_t fd) {
ASSERT(fd >= 0);
struct sockaddr_in socket_address;
socklen_t size = sizeof(socket_address);
if (getsockname(fd, reinterpret_cast<struct sockaddr *>(&socket_address),
&size)) {
if (TEMP_FAILURE_RETRY(
getsockname(fd,
reinterpret_cast<struct sockaddr *>(&socket_address),
&size))) {
fprintf(stderr, "Error getsockname: %s\n", strerror(errno));
return 0;
}
@ -105,33 +108,36 @@ intptr_t Socket::GetStdioHandle(int num) {
intptr_t ServerSocket::CreateBindListen(const char* host,
intptr_t port,
intptr_t backlog) {
intptr_t port,
intptr_t backlog) {
intptr_t fd;
struct sockaddr_in server_address;
fd = socket(AF_INET, SOCK_STREAM, 0);
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
if (fd < 0) {
fprintf(stderr, "Error CreateBind: %s\n", strerror(errno));
return -1;
}
int optval = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
TEMP_FAILURE_RETRY(
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = inet_addr(host);
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
if (bind(fd, reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address)) < 0) {
close(fd);
if (TEMP_FAILURE_RETRY(
bind(fd,
reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address))) < 0) {
TEMP_FAILURE_RETRY(close(fd));
fprintf(stderr, "Error Bind: %s\n", strerror(errno));
return -1;
}
if (listen(fd, backlog) != 0) {
if (TEMP_FAILURE_RETRY(listen(fd, backlog)) != 0) {
fprintf(stderr, "Error Listen: %s\n", strerror(errno));
return -1;
}
@ -144,7 +150,7 @@ intptr_t ServerSocket::Accept(intptr_t fd) {
intptr_t socket;
struct sockaddr clientaddr;
socklen_t addrlen = sizeof(clientaddr);
socket = accept(fd, &clientaddr, &addrlen);
socket = TEMP_FAILURE_RETRY(accept(fd, &clientaddr, &addrlen));
if (socket < 0) {
fprintf(stderr, "Error Accept: %s\n", strerror(errno));
} else {

View file

@ -1,4 +1,4 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -26,7 +26,7 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
struct hostent* server;
struct sockaddr_in server_address;
fd = socket(AF_INET, SOCK_STREAM, 0);
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
if (fd < 0) {
fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
return -1;
@ -36,7 +36,7 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
server = gethostbyname(host);
if (server == NULL) {
close(fd);
TEMP_FAILURE_RETRY(close(fd));
fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
return -1;
}
@ -45,9 +45,10 @@ intptr_t Socket::CreateConnect(const char* host, const intptr_t port) {
server_address.sin_port = htons(port);
bcopy(server->h_addr, &server_address.sin_addr.s_addr, server->h_length);
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
intptr_t result = connect(fd,
reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address));
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd,
reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address)));
if (result == 0 || errno == EINPROGRESS) {
return fd;
}
@ -62,11 +63,11 @@ intptr_t Socket::Available(intptr_t fd) {
int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
ASSERT(fd >= 0);
ssize_t read_bytes = read(fd, buffer, num_bytes);
if (read_bytes == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) {
// If the read was interrupted or the read would block we need
// to retry and therefore return 0 as the number of bytes written.
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if (read_bytes == -1 && errno == EWOULDBLOCK) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
}
return read_bytes;
@ -75,11 +76,11 @@ int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
ASSERT(fd >= 0);
ssize_t written_bytes = write(fd, buffer, num_bytes);
if (written_bytes == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) {
// If the write was interrupted or the write would block we need
// to retry and therefore return 0 as the number of bytes written.
ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
if (written_bytes == -1 && errno == EWOULDBLOCK) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
}
return written_bytes;
@ -90,8 +91,10 @@ intptr_t Socket::GetPort(intptr_t fd) {
ASSERT(fd >= 0);
struct sockaddr_in socket_address;
socklen_t size = sizeof(socket_address);
if (getsockname(fd, reinterpret_cast<struct sockaddr *>(&socket_address),
&size)) {
if (TEMP_FAILURE_RETRY(
getsockname(fd,
reinterpret_cast<struct sockaddr *>(&socket_address),
&size))) {
fprintf(stderr, "Error getsockname: %s\n", strerror(errno));
return 0;
}
@ -105,33 +108,36 @@ intptr_t Socket::GetStdioHandle(int num) {
intptr_t ServerSocket::CreateBindListen(const char* host,
intptr_t port,
intptr_t backlog) {
intptr_t port,
intptr_t backlog) {
intptr_t fd;
struct sockaddr_in server_address;
fd = socket(AF_INET, SOCK_STREAM, 0);
fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
if (fd < 0) {
fprintf(stderr, "Error CreateBind: %s\n", strerror(errno));
return -1;
}
int optval = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
TEMP_FAILURE_RETRY(
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = inet_addr(host);
memset(&server_address.sin_zero, 0, sizeof(server_address.sin_zero));
if (bind(fd, reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address)) < 0) {
close(fd);
if (TEMP_FAILURE_RETRY(
bind(fd,
reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address))) < 0) {
TEMP_FAILURE_RETRY(close(fd));
fprintf(stderr, "Error Bind: %s\n", strerror(errno));
return -1;
}
if (listen(fd, backlog) != 0) {
if (TEMP_FAILURE_RETRY(listen(fd, backlog)) != 0) {
fprintf(stderr, "Error Listen: %s\n", strerror(errno));
return -1;
}
@ -144,7 +150,7 @@ intptr_t ServerSocket::Accept(intptr_t fd) {
intptr_t socket;
struct sockaddr clientaddr;
socklen_t addrlen = sizeof(clientaddr);
socket = accept(fd, &clientaddr, &addrlen);
socket = TEMP_FAILURE_RETRY(accept(fd, &clientaddr, &addrlen));
if (socket < 0) {
fprintf(stderr, "Error Accept: %s\n", strerror(errno));
} else {

View file

@ -39,6 +39,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#if defined(_WIN32)
#include "platform/c99_support_win.h"
@ -102,4 +103,17 @@ static inline void USE(T) { }
#define strtok_r strtok_s
#endif
#if !defined(TARGET_OS_WINDOWS) && !defined(TEMP_FAILURE_RETRY)
// TEMP_FAILURE_RETRY is defined in unistd.h on some platforms. The
// definition below is copied from Linux and adapted to avoid lint
// errors (type long int changed to int64_t and do/while split on
// separate lines with body in {}s).
# define TEMP_FAILURE_RETRY(expression) \
({ int64_t __result; \
do { \
__result = (int64_t) (expression); \
} while (__result == -1L && errno == EINTR); \
__result; })
#endif
#endif // PLATFORM_GLOBALS_H_