summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vm/native/dalvik_system_Zygote.cpp29
1 files changed, 29 insertions, 0 deletions
diff --git a/vm/native/dalvik_system_Zygote.cpp b/vm/native/dalvik_system_Zygote.cpp
index 1bcaac5c7..e892378cf 100644
--- a/vm/native/dalvik_system_Zygote.cpp
+++ b/vm/native/dalvik_system_Zygote.cpp
@@ -677,6 +677,23 @@ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer, bool l
dvmDumpLoaderStats("zygote");
+ sigset_t sigchld;
+ sigemptyset(&sigchld);
+ sigaddset(&sigchld, SIGCHLD);
+
+ // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
+ // log, which would result in the logging FDs we close being
+ // reopened.
+ // This would cause failures because the FDs are not whitelisted.
+ //
+ // Note that the zygote process is single threaded at this
+ // point.
+ if (sigprocmask(SIG_BLOCK, &sigchld, NULL) == -1) {
+ ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
+ dvmAbort();
+ }
+
+
// Close any logging related FDs before we start evaluating the list of
// file descriptors.
__android_log_close();
@@ -742,6 +759,11 @@ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer, bool l
ALOGE("Unable to reopen whitelisted descriptors.");
dvmAbort();
}
+
+ if (sigprocmask(SIG_UNBLOCK, &sigchld, NULL) == -1) {
+ ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
+ dvmAbort();
+ }
#endif /* HAVE_ANDROID_OS */
if (mountMode != MOUNT_EXTERNAL_NONE) {
@@ -844,6 +866,13 @@ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer, bool l
/* the parent process */
free(seInfo);
free(niceName);
+
+ // We blocked SIGCHLD prior to a fork, we unblock it here.
+ if (sigprocmask(SIG_UNBLOCK, &sigchld, NULL) == -1) {
+ ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
+ dvmAbort();
+ }
+
}
return pid;