summaryrefslogtreecommitdiffstats
path: root/luni-kernel/src
diff options
context:
space:
mode:
authorcrazybob <crazybob@google.com>2009-06-18 17:19:04 -0500
committercrazybob <crazybob@google.com>2009-07-01 11:39:10 -0500
commit410530d90797fd49ad34c76a05a2c8f5147f88e1 (patch)
treef257b5a11815d8a556f68846605615acae312246 /luni-kernel/src
parenteeff8168c7dddfd360c0b80b8b8e00c970f0dd91 (diff)
downloadlibcore-410530d90797fd49ad34c76a05a2c8f5147f88e1.zip
libcore-410530d90797fd49ad34c76a05a2c8f5147f88e1.tar.gz
libcore-410530d90797fd49ad34c76a05a2c8f5147f88e1.tar.bz2
Fixes deadlock in Runtime.exec(). We can't malloc() or free() after fork() because the heap lock may be held by a thread that is no longer running.
Diffstat (limited to 'luni-kernel/src')
-rw-r--r--luni-kernel/src/main/native/java_lang_ProcessManager.c32
1 files changed, 14 insertions, 18 deletions
diff --git a/luni-kernel/src/main/native/java_lang_ProcessManager.c b/luni-kernel/src/main/native/java_lang_ProcessManager.c
index ee2fc58..fcff1df 100644
--- a/luni-kernel/src/main/native/java_lang_ProcessManager.c
+++ b/luni-kernel/src/main/native/java_lang_ProcessManager.c
@@ -16,6 +16,7 @@
#define LOG_TAG "ProcessManager"
+#include <sys/resource.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -24,7 +25,6 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include <dirent.h>
#include "jni.h"
#include "JNIHelp.h"
@@ -155,31 +155,21 @@ static void java_lang_ProcessManager_watchChildren(JNIEnv* env, jobject o) {
}
}
-/** Close all open fds > 2 (i.e. everything but stdin/out/err). */
+/** Close all open fds > 2 (i.e. everything but stdin/out/err), != skipFd. */
static void closeNonStandardFds(int skipFd) {
- DIR* dir = opendir("/proc/self/fd");
+ struct rlimit rlimit;
+ getrlimit(RLIMIT_NOFILE, &rlimit);
- if (dir == NULL) {
- // Print message to standard err. The parent process can read this
- // from Process.getErrorStream().
- perror("opendir");
- return;
- }
-
- struct dirent* entry;
- int dirFd = dirfd(dir);
- while ((entry = readdir(dir)) != NULL) {
- int fd = atoi(entry->d_name);
- if (fd > 2 && fd != dirFd && fd != skipFd
+ int fd;
+ for (fd = 3; fd < rlimit.rlim_max; fd++) {
+ if (fd != skipFd
#ifdef ANDROID
&& fd != androidSystemPropertiesFd
#endif
) {
close(fd);
- }
+ }
}
-
- closedir(dir);
}
#define PIPE_COUNT (4) // number of pipes used to communicate with child proc
@@ -233,6 +223,12 @@ static pid_t executeProcess(JNIEnv* env, char** commands, char** environment,
// If this is the child process...
if (childPid == 0) {
+ /*
+ * Note: We cannot malloc() or free() after this point!
+ * A no-longer-running thread may be holding on to the heap lock, and
+ * an attempt to malloc() or free() would result in deadlock.
+ */
+
// Replace stdin, out, and err with pipes.
dup2(stdinIn, 0);
dup2(stdoutOut, 1);