From 0122a33a76a2ccdd0de28c31c7b8a9f9d7f99529 Mon Sep 17 00:00:00 2001 From: "sgjesse@google.com" Date: Wed, 11 Jan 2012 15:12:27 +0000 Subject: [PATCH] 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 --- runtime/bin/directory_posix.cc | 29 ++++-- runtime/bin/eventhandler_linux.cc | 28 +++--- runtime/bin/eventhandler_macos.cc | 30 ++++--- runtime/bin/fdutils_linux.cc | 43 ++++----- runtime/bin/fdutils_macos.cc | 43 ++++----- runtime/bin/file_linux.cc | 34 +++---- runtime/bin/file_macos.cc | 46 +++++----- runtime/bin/process_linux.cc | 144 +++++++++++++++--------------- runtime/bin/process_macos.cc | 144 +++++++++++++++--------------- runtime/bin/socket_linux.cc | 60 +++++++------ runtime/bin/socket_macos.cc | 60 +++++++------ runtime/platform/globals.h | 14 +++ 12 files changed, 367 insertions(+), 308 deletions(-) diff --git a/runtime/bin/directory_posix.cc b/runtime/bin/directory_posix.cc index 8d79697c947..c201988325b 100644 --- a/runtime/bin/directory_posix.cc +++ b/runtime/bin/directory_posix.cc @@ -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); } diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc index bad82ab1ab9..296fafba1eb 100644 --- a/runtime/bin/eventhandler_linux.cc +++ b/runtime/bin/eventhandler_linux.cc @@ -55,7 +55,7 @@ EventHandlerImplementation::EventHandlerImplementation() { socket_map_ = reinterpret_cast(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(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 { diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc index 526fd55bb98..d3fe8c80af2 100644 --- a/runtime/bin/eventhandler_macos.cc +++ b/runtime/bin/eventhandler_macos.cc @@ -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(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(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 { diff --git a/runtime/bin/fdutils_linux.cc b/runtime/bin/fdutils_linux.cc index d92b6608c52..4aeccb4b676 100644 --- a/runtime/bin/fdutils_linux.cc +++ b/runtime/bin/fdutils_linux.cc @@ -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(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(reinterpret_cast(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; diff --git a/runtime/bin/fdutils_macos.cc b/runtime/bin/fdutils_macos.cc index d92b6608c52..4aeccb4b676 100644 --- a/runtime/bin/fdutils_macos.cc +++ b/runtime/bin/fdutils_macos.cc @@ -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(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(reinterpret_cast(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; diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc index 665240b6524..00a0e4ec223 100644 --- a/runtime/bin/file_linux.cc +++ b/runtime/bin/file_linux.cc @@ -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; diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc index 25387bdac03..3187f9040fb 100644 --- a/runtime/bin/file_macos.cc +++ b/runtime/bin/file_macos.cc @@ -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(malloc(PATH_MAX+1)); + char* resolved_path = reinterpret_cast(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; diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc index 12e00218a6b..94af186d56b 100644 --- a/runtime/bin/process_linux.cc +++ b/runtime/bin/process_linux.cc @@ -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(program_arguments)); + TEMP_FAILURE_RETRY( + execvp(path, const_cast(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; } diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc index 616632a2368..c42b08114d0 100644 --- a/runtime/bin/process_macos.cc +++ b/runtime/bin/process_macos.cc @@ -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(program_arguments)); + TEMP_FAILURE_RETRY( + execvp(path, const_cast(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; } diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc index 39e5edb5e74..bc4cd932a7f 100644 --- a/runtime/bin/socket_linux.cc +++ b/runtime/bin/socket_linux.cc @@ -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(&server_address), - sizeof(server_address)); + intptr_t result = TEMP_FAILURE_RETRY( + connect(fd, + reinterpret_cast(&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(&socket_address), - &size)) { + if (TEMP_FAILURE_RETRY( + getsockname(fd, + reinterpret_cast(&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(&server_address), - sizeof(server_address)) < 0) { - close(fd); + if (TEMP_FAILURE_RETRY( + bind(fd, + reinterpret_cast(&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 { diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc index c75cc454b76..0e4acd0f850 100644 --- a/runtime/bin/socket_macos.cc +++ b/runtime/bin/socket_macos.cc @@ -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(&server_address), - sizeof(server_address)); + intptr_t result = TEMP_FAILURE_RETRY( + connect(fd, + reinterpret_cast(&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(&socket_address), - &size)) { + if (TEMP_FAILURE_RETRY( + getsockname(fd, + reinterpret_cast(&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(&server_address), - sizeof(server_address)) < 0) { - close(fd); + if (TEMP_FAILURE_RETRY( + bind(fd, + reinterpret_cast(&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 { diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h index fe7331827fa..ad5aabcfc56 100644 --- a/runtime/platform/globals.h +++ b/runtime/platform/globals.h @@ -39,6 +39,7 @@ #include #include #include +#include #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_