Merge "Add Zygote.startChildZygote() to fork a new process that itself is a zygote."
This commit is contained in:
44
core/java/android/os/ChildZygoteProcess.java
Normal file
44
core/java/android/os/ChildZygoteProcess.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.os;
|
||||
|
||||
import android.net.LocalSocketAddress;
|
||||
|
||||
/**
|
||||
* Represents a connection to a child-zygote process. A child-zygote is spawend from another
|
||||
* zygote process using {@link startChildZygote()}.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public class ChildZygoteProcess extends ZygoteProcess {
|
||||
/**
|
||||
* The PID of the child zygote process.
|
||||
*/
|
||||
private final int mPid;
|
||||
|
||||
ChildZygoteProcess(LocalSocketAddress socketAddress, int pid) {
|
||||
super(socketAddress, null);
|
||||
mPid = pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PID of the child-zygote process.
|
||||
*/
|
||||
public int getPid() {
|
||||
return mPid;
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/*package*/ class ZygoteStartFailedEx extends Exception {
|
||||
ZygoteStartFailedEx(String s) {
|
||||
@@ -217,7 +218,8 @@ public class ZygoteProcess {
|
||||
try {
|
||||
return startViaZygote(processClass, niceName, uid, gid, gids,
|
||||
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
|
||||
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
|
||||
abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
|
||||
zygoteArgs);
|
||||
} catch (ZygoteStartFailedEx ex) {
|
||||
Log.e(LOG_TAG,
|
||||
"Starting VM process through Zygote failed");
|
||||
@@ -333,6 +335,8 @@ public class ZygoteProcess {
|
||||
* @param abi the ABI the process should use.
|
||||
* @param instructionSet null-ok the instruction set to use.
|
||||
* @param appDataDir null-ok the data directory of the app.
|
||||
* @param startChildZygote Start a sub-zygote. This creates a new zygote process
|
||||
* that has its state cloned from this zygote process.
|
||||
* @param extraArgs Additional arguments to supply to the zygote process.
|
||||
* @return An object that describes the result of the attempt to start the process.
|
||||
* @throws ZygoteStartFailedEx if process start failed for any reason
|
||||
@@ -348,6 +352,7 @@ public class ZygoteProcess {
|
||||
String instructionSet,
|
||||
String appDataDir,
|
||||
String invokeWith,
|
||||
boolean startChildZygote,
|
||||
String[] extraArgs)
|
||||
throws ZygoteStartFailedEx {
|
||||
ArrayList<String> argsForZygote = new ArrayList<String>();
|
||||
@@ -404,6 +409,10 @@ public class ZygoteProcess {
|
||||
argsForZygote.add(invokeWith);
|
||||
}
|
||||
|
||||
if (startChildZygote) {
|
||||
argsForZygote.add("--start-child-zygote");
|
||||
}
|
||||
|
||||
argsForZygote.add(processClass);
|
||||
|
||||
if (extraArgs != null) {
|
||||
@@ -417,6 +426,18 @@ public class ZygoteProcess {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the connections to the zygote, if they exist.
|
||||
*/
|
||||
public void close() {
|
||||
if (primaryZygoteState != null) {
|
||||
primaryZygoteState.close();
|
||||
}
|
||||
if (secondaryZygoteState != null) {
|
||||
secondaryZygoteState.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to establish a connection to the zygote that handles a given {@code abi}. Might block
|
||||
* and retry if the zygote is unresponsive. This method is a no-op if a connection is
|
||||
@@ -549,4 +570,36 @@ public class ZygoteProcess {
|
||||
}
|
||||
Slog.wtf(LOG_TAG, "Failed to connect to Zygote through socket " + address.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new zygote process as a child of this zygote. This is used to create
|
||||
* secondary zygotes that inherit data from the zygote that this object
|
||||
* communicates with. This returns a new ZygoteProcess representing a connection
|
||||
* to the newly created zygote. Throws an exception if the zygote cannot be started.
|
||||
*/
|
||||
public ChildZygoteProcess startChildZygote(final String processClass,
|
||||
final String niceName,
|
||||
int uid, int gid, int[] gids,
|
||||
int runtimeFlags,
|
||||
String seInfo,
|
||||
String abi,
|
||||
String instructionSet) {
|
||||
// Create an unguessable address in the global abstract namespace.
|
||||
final LocalSocketAddress serverAddress = new LocalSocketAddress(
|
||||
processClass + "/" + UUID.randomUUID().toString());
|
||||
|
||||
final String[] extraArgs = {Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG + serverAddress.getName()};
|
||||
|
||||
Process.ProcessStartResult result;
|
||||
try {
|
||||
result = startViaZygote(processClass, niceName, uid, gid,
|
||||
gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
|
||||
abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
|
||||
true /* startChildZygote */, extraArgs);
|
||||
} catch (ZygoteStartFailedEx ex) {
|
||||
throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
|
||||
}
|
||||
|
||||
return new ChildZygoteProcess(serverAddress, result.pid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ public class RuntimeInit {
|
||||
* @param argv Argument vector for main()
|
||||
* @param classLoader the classLoader to load {@className} with
|
||||
*/
|
||||
private static Runnable findStaticMain(String className, String[] argv,
|
||||
protected static Runnable findStaticMain(String className, String[] argv,
|
||||
ClassLoader classLoader) {
|
||||
Class<?> cl;
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ class WebViewZygoteInit {
|
||||
|
||||
final Runnable caller;
|
||||
try {
|
||||
sServer.registerServerSocket("webview_zygote");
|
||||
sServer.registerServerSocketFromEnv("webview_zygote");
|
||||
// The select loop returns early in the child process after a fork and
|
||||
// loops forever in the zygote.
|
||||
caller = sServer.runSelectLoop(TextUtils.join(",", Build.SUPPORTED_ABIS));
|
||||
|
||||
@@ -71,6 +71,13 @@ public final class Zygote {
|
||||
|
||||
private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
|
||||
|
||||
/**
|
||||
* An extraArg passed when a zygote process is forking a child-zygote, specifying a name
|
||||
* in the abstract socket namespace. This socket name is what the new child zygote
|
||||
* should listen for connections on.
|
||||
*/
|
||||
public static final String CHILD_ZYGOTE_SOCKET_NAME_ARG = "--zygote-socket=";
|
||||
|
||||
private Zygote() {}
|
||||
|
||||
/** Called for some security initialization before any fork. */
|
||||
@@ -102,6 +109,8 @@ public final class Zygote {
|
||||
* @param fdsToIgnore null-ok an array of ints, either null or holding
|
||||
* one or more POSIX file descriptor numbers that are to be ignored
|
||||
* in the file descriptor table check.
|
||||
* @param startChildZygote if true, the new child process will itself be a
|
||||
* new zygote process.
|
||||
* @param instructionSet null-ok the instruction set to use.
|
||||
* @param appDataDir null-ok the data directory of the app.
|
||||
*
|
||||
@@ -110,13 +119,13 @@ public final class Zygote {
|
||||
*/
|
||||
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
|
||||
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
|
||||
int[] fdsToIgnore, String instructionSet, String appDataDir) {
|
||||
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) {
|
||||
VM_HOOKS.preFork();
|
||||
// Resets nice priority for zygote process.
|
||||
resetNicePriority();
|
||||
int pid = nativeForkAndSpecialize(
|
||||
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
|
||||
fdsToIgnore, instructionSet, appDataDir);
|
||||
fdsToIgnore, startChildZygote, instructionSet, appDataDir);
|
||||
// Enable tracing as soon as possible for the child process.
|
||||
if (pid == 0) {
|
||||
Trace.setTracingEnabled(true, runtimeFlags);
|
||||
@@ -130,7 +139,7 @@ public final class Zygote {
|
||||
|
||||
native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int runtimeFlags,
|
||||
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
|
||||
int[] fdsToIgnore, String instructionSet, String appDataDir);
|
||||
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir);
|
||||
|
||||
/**
|
||||
* Called to do any initialization before starting an application.
|
||||
@@ -190,8 +199,8 @@ public final class Zygote {
|
||||
native protected static void nativeUnmountStorageOnInit();
|
||||
|
||||
private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
|
||||
String instructionSet) {
|
||||
VM_HOOKS.postForkChild(runtimeFlags, isSystemServer, instructionSet);
|
||||
boolean isZygote, String instructionSet) {
|
||||
VM_HOOKS.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -221,8 +221,8 @@ class ZygoteConnection {
|
||||
|
||||
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
|
||||
parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
|
||||
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
|
||||
parsedArgs.appDataDir);
|
||||
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
|
||||
parsedArgs.instructionSet, parsedArgs.appDataDir);
|
||||
|
||||
try {
|
||||
if (pid == 0) {
|
||||
@@ -233,7 +233,8 @@ class ZygoteConnection {
|
||||
IoUtils.closeQuietly(serverPipeFd);
|
||||
serverPipeFd = null;
|
||||
|
||||
return handleChildProc(parsedArgs, descriptors, childPipeFd);
|
||||
return handleChildProc(parsedArgs, descriptors, childPipeFd,
|
||||
parsedArgs.startChildZygote);
|
||||
} else {
|
||||
// In the parent. A pid < 0 indicates a failure and will be handled in
|
||||
// handleParentProc.
|
||||
@@ -414,6 +415,14 @@ class ZygoteConnection {
|
||||
*/
|
||||
boolean preloadDefault;
|
||||
|
||||
/**
|
||||
* Whether this is a request to start a zygote process as a child of this zygote.
|
||||
* Set with --start-child-zygote. The remaining arguments must include the
|
||||
* CHILD_ZYGOTE_SOCKET_NAME_ARG flag to indicate the abstract socket name that
|
||||
* should be used for communication.
|
||||
*/
|
||||
boolean startChildZygote;
|
||||
|
||||
/**
|
||||
* Constructs instance and parses args
|
||||
* @param args zygote command-line args
|
||||
@@ -565,6 +574,8 @@ class ZygoteConnection {
|
||||
preloadPackageCacheKey = args[++curArg];
|
||||
} else if (arg.equals("--preload-default")) {
|
||||
preloadDefault = true;
|
||||
} else if (arg.equals("--start-child-zygote")) {
|
||||
startChildZygote = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -587,6 +598,20 @@ class ZygoteConnection {
|
||||
remainingArgs = new String[args.length - curArg];
|
||||
System.arraycopy(args, curArg, remainingArgs, 0, remainingArgs.length);
|
||||
}
|
||||
|
||||
if (startChildZygote) {
|
||||
boolean seenChildSocketArg = false;
|
||||
for (String arg : remainingArgs) {
|
||||
if (arg.startsWith(Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG)) {
|
||||
seenChildSocketArg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!seenChildSocketArg) {
|
||||
throw new IllegalArgumentException("--start-child-zygote specified " +
|
||||
"without " + Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -739,9 +764,10 @@ class ZygoteConnection {
|
||||
* @param parsedArgs non-null; zygote args
|
||||
* @param descriptors null-ok; new file descriptors for stdio if available.
|
||||
* @param pipeFd null-ok; pipe for communication back to Zygote.
|
||||
* @param isZygote whether this new child process is itself a new Zygote.
|
||||
*/
|
||||
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
|
||||
FileDescriptor pipeFd) {
|
||||
FileDescriptor pipeFd, boolean isZygote) {
|
||||
/**
|
||||
* By the time we get here, the native code has closed the two actual Zygote
|
||||
* socket connections, and substituted /dev/null in their place. The LocalSocket
|
||||
@@ -778,8 +804,13 @@ class ZygoteConnection {
|
||||
// Should not get here.
|
||||
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
|
||||
} else {
|
||||
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
|
||||
null /* classLoader */);
|
||||
if (!isZygote) {
|
||||
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
|
||||
null /* classLoader */);
|
||||
} else {
|
||||
return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
|
||||
parsedArgs.remainingArgs, null /* classLoader */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -756,7 +756,7 @@ public class ZygoteInit {
|
||||
throw new RuntimeException("No ABI list supplied.");
|
||||
}
|
||||
|
||||
zygoteServer.registerServerSocket(socketName);
|
||||
zygoteServer.registerServerSocketFromEnv(socketName);
|
||||
// In some configurations, we avoid preloading resources and classes eagerly.
|
||||
// In such cases, we will preload things prior to our first fork.
|
||||
if (!enableLazyPreload) {
|
||||
@@ -871,5 +871,16 @@ public class ZygoteInit {
|
||||
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* The main function called when starting a child zygote process. This is used as an
|
||||
* alternative to zygoteInit(), which skips calling into initialization routines that
|
||||
* start the Binder threadpool.
|
||||
*/
|
||||
static final Runnable childZygoteInit(
|
||||
int targetSdkVersion, String[] argv, ClassLoader classLoader) {
|
||||
RuntimeInit.Arguments args = new RuntimeInit.Arguments(argv);
|
||||
return RuntimeInit.findStaticMain(args.startClass, args.startArgs, classLoader);
|
||||
}
|
||||
|
||||
private static final native void nativeZygoteInit();
|
||||
}
|
||||
|
||||
@@ -44,8 +44,20 @@ class ZygoteServer {
|
||||
|
||||
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
|
||||
|
||||
/**
|
||||
* Listening socket that accepts new server connections.
|
||||
*/
|
||||
private LocalServerSocket mServerSocket;
|
||||
|
||||
/**
|
||||
* Whether or not mServerSocket's underlying FD should be closed directly.
|
||||
* If mServerSocket is created with an existing FD, closing the socket does
|
||||
* not close the FD and it must be closed explicitly. If the socket is created
|
||||
* with a name instead, then closing the socket will close the underlying FD
|
||||
* and it should not be double-closed.
|
||||
*/
|
||||
private boolean mCloseSocketFd;
|
||||
|
||||
/**
|
||||
* Set by the child process, immediately after a call to {@code Zygote.forkAndSpecialize}.
|
||||
*/
|
||||
@@ -59,11 +71,12 @@ class ZygoteServer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a server socket for zygote command connections
|
||||
* Registers a server socket for zygote command connections. This locates the server socket
|
||||
* file descriptor through an ANDROID_SOCKET_ environment variable.
|
||||
*
|
||||
* @throws RuntimeException when open fails
|
||||
*/
|
||||
void registerServerSocket(String socketName) {
|
||||
void registerServerSocketFromEnv(String socketName) {
|
||||
if (mServerSocket == null) {
|
||||
int fileDesc;
|
||||
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
|
||||
@@ -78,6 +91,7 @@ class ZygoteServer {
|
||||
FileDescriptor fd = new FileDescriptor();
|
||||
fd.setInt$(fileDesc);
|
||||
mServerSocket = new LocalServerSocket(fd);
|
||||
mCloseSocketFd = true;
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(
|
||||
"Error binding to local socket '" + fileDesc + "'", ex);
|
||||
@@ -85,6 +99,22 @@ class ZygoteServer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a server socket for zygote command connections. This opens the server socket
|
||||
* at the specified name in the abstract socket namespace.
|
||||
*/
|
||||
void registerServerSocketAtAbstractName(String socketName) {
|
||||
if (mServerSocket == null) {
|
||||
try {
|
||||
mServerSocket = new LocalServerSocket(socketName);
|
||||
mCloseSocketFd = false;
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(
|
||||
"Error binding to abstract socket '" + socketName + "'", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for and accepts a single command connection. Throws
|
||||
* RuntimeException on failure.
|
||||
@@ -112,7 +142,7 @@ class ZygoteServer {
|
||||
if (mServerSocket != null) {
|
||||
FileDescriptor fd = mServerSocket.getFileDescriptor();
|
||||
mServerSocket.close();
|
||||
if (fd != null) {
|
||||
if (fd != null && mCloseSocketFd) {
|
||||
Os.close(fd);
|
||||
}
|
||||
}
|
||||
@@ -219,6 +249,11 @@ class ZygoteServer {
|
||||
Log.e(TAG, "Caught post-fork exception in child process.", e);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
// Reset the child flag, in the event that the child process is a child-
|
||||
// zygote. The flag will not be consulted this loop pass after the Runnable
|
||||
// is returned.
|
||||
mIsForkChild = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
|
||||
jint mount_external,
|
||||
jstring java_se_info, jstring java_se_name,
|
||||
bool is_system_server, jintArray fdsToClose,
|
||||
jintArray fdsToIgnore,
|
||||
jintArray fdsToIgnore, bool is_child_zygote,
|
||||
jstring instructionSet, jstring dataDir) {
|
||||
SetSignalHandlers();
|
||||
|
||||
@@ -699,7 +699,7 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
|
||||
UnsetChldSignalHandler();
|
||||
|
||||
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
|
||||
is_system_server, instructionSet);
|
||||
is_system_server, is_child_zygote, instructionSet);
|
||||
if (env->ExceptionCheck()) {
|
||||
RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
|
||||
}
|
||||
@@ -748,8 +748,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
|
||||
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
|
||||
jint runtime_flags, jobjectArray rlimits,
|
||||
jint mount_external, jstring se_info, jstring se_name,
|
||||
jintArray fdsToClose,
|
||||
jintArray fdsToIgnore,
|
||||
jintArray fdsToClose, jintArray fdsToIgnore, jboolean is_child_zygote,
|
||||
jstring instructionSet, jstring appDataDir) {
|
||||
jlong capabilities = 0;
|
||||
|
||||
@@ -786,13 +785,22 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
|
||||
capabilities |= (1LL << CAP_BLOCK_SUSPEND);
|
||||
}
|
||||
|
||||
// If forking a child zygote process, that zygote will need to be able to change
|
||||
// the UID and GID of processes it forks, as well as drop those capabilities.
|
||||
if (is_child_zygote) {
|
||||
capabilities |= (1LL << CAP_SETUID);
|
||||
capabilities |= (1LL << CAP_SETGID);
|
||||
capabilities |= (1LL << CAP_SETPCAP);
|
||||
}
|
||||
|
||||
// Containers run without some capabilities, so drop any caps that are not
|
||||
// available.
|
||||
capabilities &= GetEffectiveCapabilityMask(env);
|
||||
|
||||
return ForkAndSpecializeCommon(env, uid, gid, gids, runtime_flags,
|
||||
rlimits, capabilities, capabilities, mount_external, se_info,
|
||||
se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir);
|
||||
se_name, false, fdsToClose, fdsToIgnore, is_child_zygote == JNI_TRUE,
|
||||
instructionSet, appDataDir);
|
||||
}
|
||||
|
||||
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
|
||||
@@ -803,7 +811,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
|
||||
runtime_flags, rlimits,
|
||||
permittedCapabilities, effectiveCapabilities,
|
||||
MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
|
||||
NULL, NULL, NULL);
|
||||
NULL, false, NULL, NULL);
|
||||
if (pid > 0) {
|
||||
// The zygote process checks whether the child process has died or not.
|
||||
ALOGI("System server process %d has been created", pid);
|
||||
@@ -877,7 +885,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{ "nativeSecurityInit", "()V",
|
||||
(void *) com_android_internal_os_Zygote_nativeSecurityInit },
|
||||
{ "nativeForkAndSpecialize",
|
||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
|
||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
|
||||
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
|
||||
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
|
||||
(void *) com_android_internal_os_Zygote_nativeForkSystemServer },
|
||||
@@ -892,7 +900,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
int register_com_android_internal_os_Zygote(JNIEnv* env) {
|
||||
gZygoteClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kZygoteClassName));
|
||||
gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkChildHooks",
|
||||
"(IZLjava/lang/String;)V");
|
||||
"(IZZLjava/lang/String;)V");
|
||||
|
||||
return RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods));
|
||||
}
|
||||
|
||||
@@ -313,10 +313,12 @@ bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is a local socket with an abstract address, we do not accept it.
|
||||
// This is a local socket with an abstract address. Remove the leading NUL byte and
|
||||
// add a human-readable "ABSTRACT/" prefix.
|
||||
if (unix_addr->sun_path[0] == '\0') {
|
||||
LOG(ERROR) << "Unsupported AF_UNIX socket (fd=" << fd << ") with abstract address.";
|
||||
return false;
|
||||
*result = "ABSTRACT/";
|
||||
result->append(&unix_addr->sun_path[1], path_len - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we're here, sun_path must refer to a null terminated filesystem
|
||||
|
||||
Reference in New Issue
Block a user