Merge "DO NOT MERGE: Add support to send notification from Zygote to system_server"
am: 54469bf6ff
Change-Id: I19f300b76010be7113feea34156a7600e8f47429
This commit is contained in:
@@ -35,6 +35,7 @@ import android.system.ErrnoException;
|
|||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import dalvik.annotation.optimization.FastNative;
|
||||||
import dalvik.system.ZygoteHooks;
|
import dalvik.system.ZygoteHooks;
|
||||||
|
|
||||||
import libcore.io.IoUtils;
|
import libcore.io.IoUtils;
|
||||||
@@ -969,4 +970,19 @@ public final class Zygote {
|
|||||||
command.append(" '").append(arg.replace("'", "'\\''")).append("'");
|
command.append(" '").append(arg.replace("'", "'\\''")).append("'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the given unsolicited zygote message as type SIGCHLD,
|
||||||
|
* extract the payload information into the given output buffer.
|
||||||
|
*
|
||||||
|
* @param in The unsolicited zygote message to be parsed
|
||||||
|
* @param length The number of bytes in the message
|
||||||
|
* @param out The output buffer where the payload information will be placed
|
||||||
|
* @return Number of elements being place into output buffer, or -1 if
|
||||||
|
* either the message is malformed or not the type as expected here.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@FastNative
|
||||||
|
public static native int nativeParseSigChld(byte[] in, int length, int[] out);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -163,6 +164,12 @@ static std::atomic_uint32_t gUsapPoolCount = 0;
|
|||||||
*/
|
*/
|
||||||
static int gUsapPoolEventFD = -1;
|
static int gUsapPoolEventFD = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The socket file descriptor used to send notifications to the
|
||||||
|
* system_server.
|
||||||
|
*/
|
||||||
|
static int gSystemServerSocketFd = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum value that the gUSAPPoolSizeMax variable may take. This value
|
* The maximum value that the gUSAPPoolSizeMax variable may take. This value
|
||||||
* is a mirror of ZygoteServer.USAP_POOL_SIZE_MAX_LIMIT
|
* is a mirror of ZygoteServer.USAP_POOL_SIZE_MAX_LIMIT
|
||||||
@@ -314,6 +321,26 @@ enum RuntimeFlags : uint32_t {
|
|||||||
PROFILE_FROM_SHELL = 1 << 15,
|
PROFILE_FROM_SHELL = 1 << 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum UnsolicitedZygoteMessageTypes : uint32_t {
|
||||||
|
UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED = 0,
|
||||||
|
UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UnsolicitedZygoteMessageSigChld {
|
||||||
|
struct {
|
||||||
|
UnsolicitedZygoteMessageTypes type;
|
||||||
|
} header;
|
||||||
|
struct {
|
||||||
|
pid_t pid;
|
||||||
|
uid_t uid;
|
||||||
|
int status;
|
||||||
|
} payload;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keep sync with services/core/java/com/android/server/am/ProcessList.java
|
||||||
|
static constexpr struct sockaddr_un kSystemServerSockAddr =
|
||||||
|
{.sun_family = AF_LOCAL, .sun_path = "/data/system/unsolzygotesocket"};
|
||||||
|
|
||||||
// Forward declaration so we don't have to move the signal handler.
|
// Forward declaration so we don't have to move the signal handler.
|
||||||
static bool RemoveUsapTableEntry(pid_t usap_pid);
|
static bool RemoveUsapTableEntry(pid_t usap_pid);
|
||||||
|
|
||||||
@@ -323,8 +350,37 @@ static void RuntimeAbort(JNIEnv* env, int line, const char* msg) {
|
|||||||
env->FatalError(oss.str().c_str());
|
env->FatalError(oss.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the socket which is going to be used to send unsolicited message
|
||||||
|
// to system_server, the socket will be closed post forking a child process.
|
||||||
|
// It's expected to be called at each zygote's initialization.
|
||||||
|
static void initUnsolSocketToSystemServer() {
|
||||||
|
gSystemServerSocketFd = socket(AF_LOCAL, SOCK_DGRAM | SOCK_NONBLOCK, 0);
|
||||||
|
if (gSystemServerSocketFd >= 0) {
|
||||||
|
ALOGV("Zygote:systemServerSocketFD = %d", gSystemServerSocketFd);
|
||||||
|
} else {
|
||||||
|
ALOGE("Unable to create socket file descriptor to connect to system_server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sendSigChildStatus(const pid_t pid, const uid_t uid, const int status) {
|
||||||
|
int socketFd = gSystemServerSocketFd;
|
||||||
|
if (socketFd >= 0) {
|
||||||
|
// fill the message buffer
|
||||||
|
struct UnsolicitedZygoteMessageSigChld data =
|
||||||
|
{.header = {.type = UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD},
|
||||||
|
.payload = {.pid = pid, .uid = uid, .status = status}};
|
||||||
|
if (TEMP_FAILURE_RETRY(
|
||||||
|
sendto(socketFd, &data, sizeof(data), 0,
|
||||||
|
reinterpret_cast<const struct sockaddr*>(&kSystemServerSockAddr),
|
||||||
|
sizeof(kSystemServerSockAddr))) == -1) {
|
||||||
|
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
|
||||||
|
"Zygote failed to write to system_server FD: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// This signal handler is for zygote mode, since the zygote must reap its children
|
// This signal handler is for zygote mode, since the zygote must reap its children
|
||||||
static void SigChldHandler(int /*signal_number*/) {
|
static void SigChldHandler(int /*signal_number*/, siginfo_t* info, void* /*ucontext*/) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status;
|
int status;
|
||||||
int64_t usaps_removed = 0;
|
int64_t usaps_removed = 0;
|
||||||
@@ -338,6 +394,8 @@ static void SigChldHandler(int /*signal_number*/) {
|
|||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
|
|
||||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
|
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
|
||||||
|
// Notify system_server that we received a SIGCHLD
|
||||||
|
sendSigChildStatus(pid, info->si_uid, status);
|
||||||
// Log process-death status that we care about.
|
// Log process-death status that we care about.
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
|
async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
|
||||||
@@ -411,8 +469,7 @@ static void SigChldHandler(int /*signal_number*/) {
|
|||||||
// This ends up being called repeatedly before each fork(), but there's
|
// This ends up being called repeatedly before each fork(), but there's
|
||||||
// no real harm in that.
|
// no real harm in that.
|
||||||
static void SetSignalHandlers() {
|
static void SetSignalHandlers() {
|
||||||
struct sigaction sig_chld = {};
|
struct sigaction sig_chld = {.sa_flags = SA_SIGINFO, .sa_sigaction = SigChldHandler};
|
||||||
sig_chld.sa_handler = SigChldHandler;
|
|
||||||
|
|
||||||
if (sigaction(SIGCHLD, &sig_chld, nullptr) < 0) {
|
if (sigaction(SIGCHLD, &sig_chld, nullptr) < 0) {
|
||||||
ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
|
ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
|
||||||
@@ -967,6 +1024,9 @@ static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
|
|||||||
|
|
||||||
// Turn fdsan back on.
|
// Turn fdsan back on.
|
||||||
android_fdsan_set_error_level(fdsan_error_level);
|
android_fdsan_set_error_level(fdsan_error_level);
|
||||||
|
|
||||||
|
// Reset the fd to the unsolicited zygote socket
|
||||||
|
gSystemServerSocketFd = -1;
|
||||||
} else {
|
} else {
|
||||||
ALOGD("Forked child process %d", pid);
|
ALOGD("Forked child process %d", pid);
|
||||||
}
|
}
|
||||||
@@ -1146,6 +1206,10 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_child_zygote) {
|
||||||
|
initUnsolSocketToSystemServer();
|
||||||
|
}
|
||||||
|
|
||||||
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
|
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
|
||||||
is_system_server, is_child_zygote, managed_instruction_set);
|
is_system_server, is_child_zygote, managed_instruction_set);
|
||||||
|
|
||||||
@@ -1391,6 +1455,11 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
|
|||||||
fds_to_ignore.push_back(gUsapPoolEventFD);
|
fds_to_ignore.push_back(gUsapPoolEventFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gSystemServerSocketFd != -1) {
|
||||||
|
fds_to_close.push_back(gSystemServerSocketFd);
|
||||||
|
fds_to_ignore.push_back(gSystemServerSocketFd);
|
||||||
|
}
|
||||||
|
|
||||||
pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true);
|
pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true);
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
@@ -1416,6 +1485,11 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
|
|||||||
fds_to_ignore.push_back(gUsapPoolEventFD);
|
fds_to_ignore.push_back(gUsapPoolEventFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gSystemServerSocketFd != -1) {
|
||||||
|
fds_to_close.push_back(gSystemServerSocketFd);
|
||||||
|
fds_to_ignore.push_back(gSystemServerSocketFd);
|
||||||
|
}
|
||||||
|
|
||||||
pid_t pid = ForkCommon(env, true,
|
pid_t pid = ForkCommon(env, true,
|
||||||
fds_to_close,
|
fds_to_close,
|
||||||
fds_to_ignore,
|
fds_to_ignore,
|
||||||
@@ -1483,6 +1557,9 @@ static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env,
|
|||||||
fds_to_close.push_back(gZygoteSocketFD);
|
fds_to_close.push_back(gZygoteSocketFD);
|
||||||
fds_to_close.push_back(gUsapPoolEventFD);
|
fds_to_close.push_back(gUsapPoolEventFD);
|
||||||
fds_to_close.insert(fds_to_close.end(), session_socket_fds.begin(), session_socket_fds.end());
|
fds_to_close.insert(fds_to_close.end(), session_socket_fds.begin(), session_socket_fds.end());
|
||||||
|
if (gSystemServerSocketFd != -1) {
|
||||||
|
fds_to_close.push_back(gSystemServerSocketFd);
|
||||||
|
}
|
||||||
|
|
||||||
fds_to_ignore.push_back(gZygoteSocketFD);
|
fds_to_ignore.push_back(gZygoteSocketFD);
|
||||||
fds_to_ignore.push_back(gUsapPoolSocketFD);
|
fds_to_ignore.push_back(gUsapPoolSocketFD);
|
||||||
@@ -1490,6 +1567,9 @@ static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env,
|
|||||||
fds_to_ignore.push_back(read_pipe_fd);
|
fds_to_ignore.push_back(read_pipe_fd);
|
||||||
fds_to_ignore.push_back(write_pipe_fd);
|
fds_to_ignore.push_back(write_pipe_fd);
|
||||||
fds_to_ignore.insert(fds_to_ignore.end(), session_socket_fds.begin(), session_socket_fds.end());
|
fds_to_ignore.insert(fds_to_ignore.end(), session_socket_fds.begin(), session_socket_fds.end());
|
||||||
|
if (gSystemServerSocketFd != -1) {
|
||||||
|
fds_to_ignore.push_back(gSystemServerSocketFd);
|
||||||
|
}
|
||||||
|
|
||||||
pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore,
|
pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore,
|
||||||
is_priority_fork == JNI_TRUE);
|
is_priority_fork == JNI_TRUE);
|
||||||
@@ -1590,6 +1670,7 @@ static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jc
|
|||||||
ALOGE("Unable to fetch USAP pool socket file descriptor");
|
ALOGE("Unable to fetch USAP pool socket file descriptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initUnsolSocketToSystemServer();
|
||||||
/*
|
/*
|
||||||
* Security Initialization
|
* Security Initialization
|
||||||
*/
|
*/
|
||||||
@@ -1733,6 +1814,44 @@ static void com_android_internal_os_Zygote_nativeBoostUsapPriority(JNIEnv* env,
|
|||||||
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
|
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static jint com_android_internal_os_Zygote_nativeParseSigChld(JNIEnv* env, jclass, jbyteArray in,
|
||||||
|
jint length, jintArray out) {
|
||||||
|
if (length != sizeof(struct UnsolicitedZygoteMessageSigChld)) {
|
||||||
|
// Apparently it's not the message we are expecting.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (in == nullptr || out == nullptr) {
|
||||||
|
// Invalid parameter
|
||||||
|
jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ScopedByteArrayRO source(env, in);
|
||||||
|
if (source.size() < length) {
|
||||||
|
// Invalid parameter
|
||||||
|
jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const struct UnsolicitedZygoteMessageSigChld* msg =
|
||||||
|
reinterpret_cast<const struct UnsolicitedZygoteMessageSigChld*>(source.get());
|
||||||
|
|
||||||
|
switch (msg->header.type) {
|
||||||
|
case UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD: {
|
||||||
|
ScopedIntArrayRW buf(env, out);
|
||||||
|
if (buf.size() != 3) {
|
||||||
|
jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
|
||||||
|
return UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED;
|
||||||
|
}
|
||||||
|
buf[0] = msg->payload.pid;
|
||||||
|
buf[1] = msg->payload.uid;
|
||||||
|
buf[2] = msg->payload.status;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static const JNINativeMethod gMethods[] = {
|
static const JNINativeMethod gMethods[] = {
|
||||||
{ "nativeForkAndSpecialize",
|
{ "nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
|
||||||
@@ -1769,7 +1888,9 @@ static const JNINativeMethod gMethods[] = {
|
|||||||
{ "nativeUnblockSigTerm", "()V",
|
{ "nativeUnblockSigTerm", "()V",
|
||||||
(void* ) com_android_internal_os_Zygote_nativeUnblockSigTerm },
|
(void* ) com_android_internal_os_Zygote_nativeUnblockSigTerm },
|
||||||
{ "nativeBoostUsapPriority", "()V",
|
{ "nativeBoostUsapPriority", "()V",
|
||||||
(void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority }
|
(void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority },
|
||||||
|
{"nativeParseSigChld", "([BI[I)I",
|
||||||
|
(void* ) com_android_internal_os_Zygote_nativeParseSigChld},
|
||||||
};
|
};
|
||||||
|
|
||||||
int register_com_android_internal_os_Zygote(JNIEnv* env) {
|
int register_com_android_internal_os_Zygote(JNIEnv* env) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
|
|||||||
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
|
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
|
||||||
import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
|
import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
|
||||||
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
|
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
|
||||||
|
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
|
||||||
import static android.os.Process.SYSTEM_UID;
|
import static android.os.Process.SYSTEM_UID;
|
||||||
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
||||||
import static android.os.Process.getFreeMemory;
|
import static android.os.Process.getFreeMemory;
|
||||||
@@ -57,6 +58,8 @@ import android.content.pm.ApplicationInfo;
|
|||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
|
import android.net.LocalSocket;
|
||||||
|
import android.net.LocalSocketAddress;
|
||||||
import android.os.AppZygote;
|
import android.os.AppZygote;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@@ -74,6 +77,7 @@ import android.os.Trace;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.storage.StorageManager;
|
import android.os.storage.StorageManager;
|
||||||
import android.os.storage.StorageManagerInternal;
|
import android.os.storage.StorageManagerInternal;
|
||||||
|
import android.system.Os;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.EventLog;
|
import android.util.EventLog;
|
||||||
@@ -102,6 +106,7 @@ import com.android.server.wm.WindowManagerService;
|
|||||||
import dalvik.system.VMRuntime;
|
import dalvik.system.VMRuntime;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileDescriptor;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -245,6 +250,10 @@ public final class ProcessList {
|
|||||||
private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE =
|
private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE =
|
||||||
"persist.device_config.runtime_native.use_app_image_startup_cache";
|
"persist.device_config.runtime_native.use_app_image_startup_cache";
|
||||||
|
|
||||||
|
// The socket path for zygote to send unsolicited msg.
|
||||||
|
// Must keep sync with com_android_internal_os_Zygote.cpp.
|
||||||
|
private static final String UNSOL_ZYGOTE_MSG_SOCKET_PATH = "/data/system/unsolzygotesocket";
|
||||||
|
|
||||||
// Low Memory Killer Daemon command codes.
|
// Low Memory Killer Daemon command codes.
|
||||||
// These must be kept in sync with lmk_cmd definitions in lmkd.h
|
// These must be kept in sync with lmk_cmd definitions in lmkd.h
|
||||||
//
|
//
|
||||||
@@ -388,6 +397,28 @@ public final class ProcessList {
|
|||||||
|
|
||||||
private PlatformCompat mPlatformCompat = null;
|
private PlatformCompat mPlatformCompat = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server socket in system_server, zygote will connect to it
|
||||||
|
* in order to send unsolicited messages to system_server.
|
||||||
|
*/
|
||||||
|
private LocalSocket mSystemServerSocketForZygote;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of bytes that an incoming unsolicited zygote message could be.
|
||||||
|
* To be updated if new message type needs to be supported.
|
||||||
|
*/
|
||||||
|
private static final int MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer to be used to receive the incoming unsolicited zygote message.
|
||||||
|
*/
|
||||||
|
private final byte[] mZygoteUnsolicitedMessage = new byte[MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer to be used to receive the SIGCHLD data, it includes pid/uid/status.
|
||||||
|
*/
|
||||||
|
private final int[] mZygoteSigChldMessage = new int[3];
|
||||||
|
|
||||||
interface LmkdKillListener {
|
interface LmkdKillListener {
|
||||||
/**
|
/**
|
||||||
* Called when there is a process kill by lmkd.
|
* Called when there is a process kill by lmkd.
|
||||||
@@ -645,6 +676,13 @@ public final class ProcessList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
// Start listening on incoming connections from zygotes.
|
||||||
|
mSystemServerSocketForZygote = createSystemServerSocketForZygote();
|
||||||
|
if (mSystemServerSocketForZygote != null) {
|
||||||
|
sKillHandler.getLooper().getQueue().addOnFileDescriptorEventListener(
|
||||||
|
mSystemServerSocketForZygote.getFileDescriptor(),
|
||||||
|
EVENT_INPUT, this::handleZygoteMessages);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3267,4 +3305,66 @@ public final class ProcessList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleZygoteSigChld(int pid, int uid, int status) {
|
||||||
|
// Just log it now.
|
||||||
|
if (DEBUG_PROCESSES) {
|
||||||
|
Slog.i(TAG, "Got SIGCHLD from zygote: pid=" + pid + ", uid=" + uid
|
||||||
|
+ ", status=" + Integer.toHexString(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a server socket in system_server, zygote will connect to it
|
||||||
|
* in order to send unsolicited messages to system_server.
|
||||||
|
*/
|
||||||
|
private LocalSocket createSystemServerSocketForZygote() {
|
||||||
|
// The file system entity for this socket is created with 0666 perms, owned
|
||||||
|
// by system:system. selinux restricts things so that only zygotes can
|
||||||
|
// access it.
|
||||||
|
final File socketFile = new File(UNSOL_ZYGOTE_MSG_SOCKET_PATH);
|
||||||
|
if (socketFile.exists()) {
|
||||||
|
socketFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalSocket serverSocket = null;
|
||||||
|
try {
|
||||||
|
serverSocket = new LocalSocket(LocalSocket.SOCKET_DGRAM);
|
||||||
|
serverSocket.bind(new LocalSocketAddress(
|
||||||
|
UNSOL_ZYGOTE_MSG_SOCKET_PATH, LocalSocketAddress.Namespace.FILESYSTEM));
|
||||||
|
Os.chmod(UNSOL_ZYGOTE_MSG_SOCKET_PATH, 0666);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (serverSocket != null) {
|
||||||
|
try {
|
||||||
|
serverSocket.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
}
|
||||||
|
serverSocket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return serverSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the unsolicited message from zygote.
|
||||||
|
*/
|
||||||
|
private int handleZygoteMessages(FileDescriptor fd, int events) {
|
||||||
|
final int eventFd = fd.getInt$();
|
||||||
|
if ((events & EVENT_INPUT) != 0) {
|
||||||
|
// An incoming message from zygote
|
||||||
|
try {
|
||||||
|
final int len = Os.read(fd, mZygoteUnsolicitedMessage, 0,
|
||||||
|
mZygoteUnsolicitedMessage.length);
|
||||||
|
if (len > 0 && mZygoteSigChldMessage.length == Zygote.nativeParseSigChld(
|
||||||
|
mZygoteUnsolicitedMessage, len, mZygoteSigChldMessage)) {
|
||||||
|
handleZygoteSigChld(mZygoteSigChldMessage[0] /* pid */,
|
||||||
|
mZygoteSigChldMessage[1] /* uid */,
|
||||||
|
mZygoteSigChldMessage[2] /* status */);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Slog.w(TAG, "Exception in reading unsolicited zygote message: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EVENT_INPUT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user