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
This commit is contained in:
Jeff Sharkey 2012-09-13 14:47:23 -07:00
parent 0f5e303c6a
commit ddb1733944
2 changed files with 23 additions and 6 deletions

View File

@ -19,6 +19,21 @@
#include <sys/types.h>
/*
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
* <unistd.h>. (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

View File

@ -14,6 +14,8 @@
* limitations under the License.
*/
#define LOG_TAG "cutils"
#include <cutils/fs.h>
#include <cutils/log.h>
@ -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;
}