From 4a31de849610fc195bf0a48b41f1ecb307635623 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 13 Sep 2012 14:47:23 -0700 Subject: Wrap system calls in TEMP_FAILURE_RETRY. fs_prepare_dir() is used heavily during Zygote init, and can easily run into EINTR. Bug: 7151474 Change-Id: I7aac43a43483d55db47ca20456fff68ce51bbc46 --- include/cutils/fs.h | 15 +++++++++++++++ libcutils/fs.c | 14 ++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/include/cutils/fs.h b/include/cutils/fs.h index 04c88399..fd5296bb 100644 --- a/include/cutils/fs.h +++ b/include/cutils/fs.h @@ -19,6 +19,21 @@ #include +/* + * TEMP_FAILURE_RETRY is defined by some, but not all, versions of + * . (Alas, it is not as standard as we'd hoped!) So, if it's + * not already defined, then define it here. + */ +#ifndef TEMP_FAILURE_RETRY +/* Used to retry syscalls that can return EINTR. */ +#define TEMP_FAILURE_RETRY(exp) ({ \ + typeof (exp) _rc; \ + do { \ + _rc = (exp); \ + } while (_rc == -1 && errno == EINTR); \ + _rc; }) +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/libcutils/fs.c b/libcutils/fs.c index 1788eca1..6508b678 100644 --- a/libcutils/fs.c +++ b/libcutils/fs.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "cutils" + #include #include @@ -31,11 +33,11 @@ int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { // Check if path needs to be created struct stat sb; - if (lstat(path, &sb) == -1) { + if (TEMP_FAILURE_RETRY(lstat(path, &sb)) == -1) { if (errno == ENOENT) { goto create; } else { - ALOGE("Failed to stat(%s): %s", path, strerror(errno)); + ALOGE("Failed to lstat(%s): %s", path, strerror(errno)); return -1; } } @@ -52,17 +54,17 @@ int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) { } create: - if (mkdir(path, mode) == -1) { + if (TEMP_FAILURE_RETRY(mkdir(path, mode)) == -1) { ALOGE("Failed to mkdir(%s): %s", path, strerror(errno)); return -1; } fixup: - if (chmod(path, mode) == -1) { - ALOGE("Failed to chown(%s, %d): %s", path, mode, strerror(errno)); + if (TEMP_FAILURE_RETRY(chmod(path, mode)) == -1) { + ALOGE("Failed to chmod(%s, %d): %s", path, mode, strerror(errno)); return -1; } - if (chown(path, uid, gid) == -1) { + if (TEMP_FAILURE_RETRY(chown(path, uid, gid)) == -1) { ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno)); return -1; } -- cgit v1.2.3