在android 4.X中有时候会出现多个system_server进程,会导致系统内存占用急速增加,系统性能下降的情况,可以尝试如下修正方法:
--- java_lang_ProcessManager.cpp
+++ java_lang_ProcessManager_new.cpp
@@ -23,7 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-
+#include <sys/wait.h>
#include "jni.h"
#include "JNIHelp.h"
#include "JniConstants.h"
@@ -60,6 +60,19 @@
}
}
+#define TEMP_FAILURE_RETRY(exp) ({ \
+ typeof (exp) _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1 && errno == EINTR); \
+ _rc; })
+
+static void AbortChild(int status_pipe_fd) {
+ int error = errno;
+ TEMP_FAILURE_RETRY(write(status_pipe_fd, &error, sizeof(int)));
+ close(status_pipe_fd);
+ _exit(127);
+}
/** Executes a command in a child process. */
static pid_t executeProcess(JNIEnv* env, char** commands, char** environment,
const char* workingDirectory, jobject inDescriptor,
@@ -129,7 +142,7 @@
// Switch to working directory.
if (workingDirectory != NULL) {
if (chdir(workingDirectory) == -1) {
- goto execFailed;
+ AbortChild(statusOut);
}
}
@@ -143,13 +156,7 @@
// should be the command itself. In fact, I get segfaults when this
// isn't the case.
execvp(commands[0], commands);
-
- // If we got here, execvp() failed or the working dir was invalid.
-execFailed:
- int error = errno;
- write(statusOut, &error, sizeof(int));
- close(statusOut);
- exit(error);
+ AbortChild(statusOut);
}
// This is the parent process.
@@ -163,16 +170,22 @@
// Check status pipe for an error code. If execvp() succeeds, the other
// end of the pipe should automatically close, in which case, we'll read
// nothing.
- int result;
- int count = read(statusIn, &result, sizeof(int));
+ int child_errno;
+ ssize_t count = TEMP_FAILURE_RETRY(read(statusIn, &child_errno, sizeof(int)));
close(statusIn);
if (count > 0) {
- jniThrowIOException(env, result);
+ jniThrowIOException(env, child_errno);
close(stdoutIn);
close(stdinOut);
close(stderrIn);
+ // Reap our zombie child right away
+ int status;
+ int rc = TEMP_FAILURE_RETRY(waitpid(childPid, &status, 0));
+ if(rc == -1) {
+ ALOGW("waitpid on failed exec failed: %s", strerror(errno));
+ }
return -1;
}