Revert "Adjusts the USAP pool refill mechanism."
This reverts commit0779af6259. Reason for revert: Breaks cts SignedConfigHostTest Note: This CL effectively reverts commit:54b8d7ea4d"Make the USAP Pool refill delay configurable." As that builds on top of the original CL being reverted. Only the ZygoteServer portion of that change is reverted. Test: atest SignedConfigHostTest (on an acloud instance) Bug: 132794985 Change-Id: I1327a22d103452bed46d191ec2bafb72a5e095ca
This commit is contained in:
@@ -172,11 +172,6 @@ public final class Zygote {
|
|||||||
*/
|
*/
|
||||||
public static final int SOCKET_BUFFER_SIZE = 256;
|
public static final int SOCKET_BUFFER_SIZE = 256;
|
||||||
|
|
||||||
/**
|
|
||||||
* @hide for internal use only
|
|
||||||
*/
|
|
||||||
private static final int PRIORITY_MAX = -20;
|
|
||||||
|
|
||||||
/** a prototype instance for a future List.toArray() */
|
/** a prototype instance for a future List.toArray() */
|
||||||
static final int[][] INT_ARRAY_2D = new int[0][0];
|
static final int[][] INT_ARRAY_2D = new int[0][0];
|
||||||
|
|
||||||
@@ -241,7 +236,8 @@ public final class Zygote {
|
|||||||
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
|
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
|
||||||
int targetSdkVersion) {
|
int targetSdkVersion) {
|
||||||
ZygoteHooks.preFork();
|
ZygoteHooks.preFork();
|
||||||
|
// Resets nice priority for zygote process.
|
||||||
|
resetNicePriority();
|
||||||
int pid = nativeForkAndSpecialize(
|
int pid = nativeForkAndSpecialize(
|
||||||
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
|
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
|
||||||
fdsToIgnore, startChildZygote, instructionSet, appDataDir);
|
fdsToIgnore, startChildZygote, instructionSet, appDataDir);
|
||||||
@@ -253,7 +249,6 @@ public final class Zygote {
|
|||||||
// Note that this event ends at the end of handleChildProc,
|
// Note that this event ends at the end of handleChildProc,
|
||||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
|
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
|
||||||
}
|
}
|
||||||
|
|
||||||
ZygoteHooks.postForkCommon();
|
ZygoteHooks.postForkCommon();
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
@@ -340,16 +335,15 @@ public final class Zygote {
|
|||||||
static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
|
static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
|
||||||
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
|
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
|
||||||
ZygoteHooks.preFork();
|
ZygoteHooks.preFork();
|
||||||
|
// Resets nice priority for zygote process.
|
||||||
|
resetNicePriority();
|
||||||
int pid = nativeForkSystemServer(
|
int pid = nativeForkSystemServer(
|
||||||
uid, gid, gids, runtimeFlags, rlimits,
|
uid, gid, gids, runtimeFlags, rlimits,
|
||||||
permittedCapabilities, effectiveCapabilities);
|
permittedCapabilities, effectiveCapabilities);
|
||||||
|
|
||||||
// Enable tracing as soon as we enter the system_server.
|
// Enable tracing as soon as we enter the system_server.
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
Trace.setTracingEnabled(true, runtimeFlags);
|
Trace.setTracingEnabled(true, runtimeFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZygoteHooks.postForkCommon();
|
ZygoteHooks.postForkCommon();
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
@@ -467,16 +461,13 @@ public final class Zygote {
|
|||||||
/**
|
/**
|
||||||
* Fork a new unspecialized app process from the zygote
|
* Fork a new unspecialized app process from the zygote
|
||||||
*
|
*
|
||||||
* @param usapPoolSocket The server socket the USAP will call accept on
|
|
||||||
* @param sessionSocketRawFDs Anonymous session sockets that are currently open
|
* @param sessionSocketRawFDs Anonymous session sockets that are currently open
|
||||||
* @param isPriorityFork Value controlling the process priority level until accept is called
|
|
||||||
* @return In the Zygote process this function will always return null; in unspecialized app
|
* @return In the Zygote process this function will always return null; in unspecialized app
|
||||||
* processes this function will return a Runnable object representing the new
|
* processes this function will return a Runnable object representing the new
|
||||||
* application that is passed up from usapMain.
|
* application that is passed up from usapMain.
|
||||||
*/
|
*/
|
||||||
static Runnable forkUsap(LocalServerSocket usapPoolSocket,
|
static Runnable forkUsap(LocalServerSocket usapPoolSocket,
|
||||||
int[] sessionSocketRawFDs,
|
int[] sessionSocketRawFDs) {
|
||||||
boolean isPriorityFork) {
|
|
||||||
FileDescriptor[] pipeFDs = null;
|
FileDescriptor[] pipeFDs = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -486,8 +477,7 @@ public final class Zygote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int pid =
|
int pid =
|
||||||
nativeForkUsap(pipeFDs[0].getInt$(), pipeFDs[1].getInt$(),
|
nativeForkUsap(pipeFDs[0].getInt$(), pipeFDs[1].getInt$(), sessionSocketRawFDs);
|
||||||
sessionSocketRawFDs, isPriorityFork);
|
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
IoUtils.closeQuietly(pipeFDs[0]);
|
IoUtils.closeQuietly(pipeFDs[0]);
|
||||||
@@ -502,8 +492,7 @@ public final class Zygote {
|
|||||||
|
|
||||||
private static native int nativeForkUsap(int readPipeFD,
|
private static native int nativeForkUsap(int readPipeFD,
|
||||||
int writePipeFD,
|
int writePipeFD,
|
||||||
int[] sessionSocketRawFDs,
|
int[] sessionSocketRawFDs);
|
||||||
boolean isPriorityFork);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used by unspecialized app processes to wait for specialization requests from
|
* This function is used by unspecialized app processes to wait for specialization requests from
|
||||||
@@ -526,11 +515,6 @@ public final class Zygote {
|
|||||||
// Load resources
|
// Load resources
|
||||||
ZygoteInit.nativePreloadGraphicsDriver();
|
ZygoteInit.nativePreloadGraphicsDriver();
|
||||||
|
|
||||||
// Change the priority to max before calling accept so we can respond to new specialization
|
|
||||||
// requests as quickly as possible. This will be reverted to the default priority in the
|
|
||||||
// native specialization code.
|
|
||||||
boostUsapPriority();
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
sessionSocket = usapPoolSocket.accept();
|
sessionSocket = usapPoolSocket.accept();
|
||||||
@@ -633,12 +617,6 @@ public final class Zygote {
|
|||||||
null /* classLoader */);
|
null /* classLoader */);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void boostUsapPriority() {
|
|
||||||
nativeBoostUsapPriority();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static native void nativeBoostUsapPriority();
|
|
||||||
|
|
||||||
static void setAppProcessName(ZygoteArguments args, String loggingTag) {
|
static void setAppProcessName(ZygoteArguments args, String loggingTag) {
|
||||||
if (args.mNiceName != null) {
|
if (args.mNiceName != null) {
|
||||||
Process.setArgV0(args.mNiceName);
|
Process.setArgV0(args.mNiceName);
|
||||||
@@ -894,6 +872,15 @@ public final class Zygote {
|
|||||||
ZygoteHooks.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
|
ZygoteHooks.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the calling thread priority to the default value (Thread.NORM_PRIORITY
|
||||||
|
* or nice value 0). This updates both the priority value in java.lang.Thread and
|
||||||
|
* the nice value (setpriority).
|
||||||
|
*/
|
||||||
|
static void resetNicePriority() {
|
||||||
|
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes "/system/bin/sh -c <command>" using the exec() system call.
|
* Executes "/system/bin/sh -c <command>" using the exec() system call.
|
||||||
* This method throws a runtime exception if exec() failed, otherwise, this
|
* This method throws a runtime exception if exec() failed, otherwise, this
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ class ZygoteConnection {
|
|||||||
if (zygoteServer.isUsapPoolEnabled()) {
|
if (zygoteServer.isUsapPoolEnabled()) {
|
||||||
Runnable fpResult =
|
Runnable fpResult =
|
||||||
zygoteServer.fillUsapPool(
|
zygoteServer.fillUsapPool(
|
||||||
new int[]{mSocket.getFileDescriptor().getInt$()}, false);
|
new int[]{mSocket.getFileDescriptor().getInt$()});
|
||||||
|
|
||||||
if (fpResult != null) {
|
if (fpResult != null) {
|
||||||
zygoteServer.setForkChild();
|
zygoteServer.setForkChild();
|
||||||
|
|||||||
@@ -822,9 +822,6 @@ public class ZygoteInit {
|
|||||||
public static void main(String argv[]) {
|
public static void main(String argv[]) {
|
||||||
ZygoteServer zygoteServer = null;
|
ZygoteServer zygoteServer = null;
|
||||||
|
|
||||||
// Set the initial thread priority to the "normal" value.
|
|
||||||
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
|
|
||||||
|
|
||||||
// Mark zygote start. This ensures that thread creation will throw
|
// Mark zygote start. This ensures that thread creation will throw
|
||||||
// an error.
|
// an error.
|
||||||
ZygoteHooks.startZygoteNoThreadCreation();
|
ZygoteHooks.startZygoteNoThreadCreation();
|
||||||
@@ -884,6 +881,8 @@ public class ZygoteInit {
|
|||||||
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
|
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
|
||||||
SystemClock.uptimeMillis());
|
SystemClock.uptimeMillis());
|
||||||
bootTimingsTraceLog.traceEnd(); // ZygotePreload
|
bootTimingsTraceLog.traceEnd(); // ZygotePreload
|
||||||
|
} else {
|
||||||
|
Zygote.resetNicePriority();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do an initial gc to clean up after startup
|
// Do an initial gc to clean up after startup
|
||||||
|
|||||||
@@ -66,12 +66,6 @@ class ZygoteServer {
|
|||||||
/** The default value used for the USAP_POOL_SIZE_MIN device property */
|
/** The default value used for the USAP_POOL_SIZE_MIN device property */
|
||||||
private static final String USAP_POOL_SIZE_MIN_DEFAULT = "1";
|
private static final String USAP_POOL_SIZE_MIN_DEFAULT = "1";
|
||||||
|
|
||||||
/** The default value used for the USAP_REFILL_DELAY_MS device property */
|
|
||||||
private static final String USAP_POOL_REFILL_DELAY_MS_DEFAULT = "3000";
|
|
||||||
|
|
||||||
/** The "not a timestamp" value for the refill delay timestamp mechanism. */
|
|
||||||
private static final int INVALID_TIMESTAMP = -1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if this Zygote server can support a unspecialized app process pool. Currently this
|
* Indicates if this Zygote server can support a unspecialized app process pool. Currently this
|
||||||
* should only be true for the primary and secondary Zygotes, and not the App Zygotes or the
|
* should only be true for the primary and secondary Zygotes, and not the App Zygotes or the
|
||||||
@@ -137,18 +131,6 @@ class ZygoteServer {
|
|||||||
*/
|
*/
|
||||||
private int mUsapPoolRefillThreshold = 0;
|
private int mUsapPoolRefillThreshold = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of milliseconds to delay before refilling the pool if it hasn't reached its
|
|
||||||
* minimum value.
|
|
||||||
*/
|
|
||||||
private int mUsapPoolRefillDelayMs = -1;
|
|
||||||
|
|
||||||
private enum UsapPoolRefillAction {
|
|
||||||
DELAYED,
|
|
||||||
IMMEDIATE,
|
|
||||||
NONE
|
|
||||||
}
|
|
||||||
|
|
||||||
ZygoteServer() {
|
ZygoteServer() {
|
||||||
mUsapPoolEventFD = null;
|
mUsapPoolEventFD = null;
|
||||||
mZygoteSocket = null;
|
mZygoteSocket = null;
|
||||||
@@ -285,13 +267,6 @@ class ZygoteServer {
|
|||||||
mUsapPoolSizeMax);
|
mUsapPoolSizeMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String usapPoolRefillDelayMsPropString = Zygote.getConfigurationProperty(
|
|
||||||
ZygoteConfig.USAP_POOL_REFILL_DELAY_MS, USAP_POOL_REFILL_DELAY_MS_DEFAULT);
|
|
||||||
|
|
||||||
if (!usapPoolRefillDelayMsPropString.isEmpty()) {
|
|
||||||
mUsapPoolRefillDelayMs = Integer.parseInt(usapPoolRefillDelayMsPropString);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (mUsapPoolSizeMin >= mUsapPoolSizeMax) {
|
if (mUsapPoolSizeMin >= mUsapPoolSizeMax) {
|
||||||
Log.w(TAG, "The max size of the USAP pool must be greater than the minimum size."
|
Log.w(TAG, "The max size of the USAP pool must be greater than the minimum size."
|
||||||
@@ -318,16 +293,9 @@ class ZygoteServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchUsapPoolPolicyPropsIfUnfetched() {
|
|
||||||
if (mIsFirstPropertyCheck) {
|
|
||||||
mIsFirstPropertyCheck = false;
|
|
||||||
fetchUsapPoolPolicyProps();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refill the USAP Pool to the appropriate level, determined by whether this is a priority
|
* Checks to see if the current policy says that pool should be refilled, and spawns new USAPs
|
||||||
* refill event or not.
|
* if necessary.
|
||||||
*
|
*
|
||||||
* @param sessionSocketRawFDs Anonymous session sockets that are currently open
|
* @param sessionSocketRawFDs Anonymous session sockets that are currently open
|
||||||
* @return In the Zygote process this function will always return null; in unspecialized app
|
* @return In the Zygote process this function will always return null; in unspecialized app
|
||||||
@@ -335,36 +303,25 @@ class ZygoteServer {
|
|||||||
* application that is passed up from usapMain.
|
* application that is passed up from usapMain.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Runnable fillUsapPool(int[] sessionSocketRawFDs, boolean isPriorityRefill) {
|
Runnable fillUsapPool(int[] sessionSocketRawFDs) {
|
||||||
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillUsapPool");
|
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillUsapPool");
|
||||||
|
|
||||||
// Ensure that the pool properties have been fetched.
|
// Ensure that the pool properties have been fetched.
|
||||||
fetchUsapPoolPolicyPropsIfUnfetched();
|
fetchUsapPoolPolicyPropsWithMinInterval();
|
||||||
|
|
||||||
int usapPoolCount = Zygote.getUsapPoolCount();
|
int usapPoolCount = Zygote.getUsapPoolCount();
|
||||||
int numUsapsToSpawn;
|
int numUsapsToSpawn = mUsapPoolSizeMax - usapPoolCount;
|
||||||
|
|
||||||
if (isPriorityRefill) {
|
if (usapPoolCount < mUsapPoolSizeMin
|
||||||
// Refill to min
|
|| numUsapsToSpawn >= mUsapPoolRefillThreshold) {
|
||||||
numUsapsToSpawn = mUsapPoolSizeMin - usapPoolCount;
|
|
||||||
|
|
||||||
Log.i("zygote",
|
|
||||||
"Priority USAP Pool refill. New USAPs: " + numUsapsToSpawn);
|
|
||||||
} else {
|
|
||||||
// Refill up to max
|
|
||||||
numUsapsToSpawn = mUsapPoolSizeMax - usapPoolCount;
|
|
||||||
|
|
||||||
Log.i("zygote",
|
|
||||||
"Delayed USAP Pool refill. New USAPs: " + numUsapsToSpawn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable some VM functionality and reset some system values
|
// Disable some VM functionality and reset some system values
|
||||||
// before forking.
|
// before forking.
|
||||||
ZygoteHooks.preFork();
|
ZygoteHooks.preFork();
|
||||||
|
Zygote.resetNicePriority();
|
||||||
|
|
||||||
while (--numUsapsToSpawn >= 0) {
|
while (usapPoolCount++ < mUsapPoolSizeMax) {
|
||||||
Runnable caller =
|
Runnable caller = Zygote.forkUsap(mUsapPoolSocket, sessionSocketRawFDs);
|
||||||
Zygote.forkUsap(mUsapPoolSocket, sessionSocketRawFDs, isPriorityRefill);
|
|
||||||
|
|
||||||
if (caller != null) {
|
if (caller != null) {
|
||||||
return caller;
|
return caller;
|
||||||
@@ -375,6 +332,10 @@ class ZygoteServer {
|
|||||||
// are re-enabled in specializeAppProcess.
|
// are re-enabled in specializeAppProcess.
|
||||||
ZygoteHooks.postForkCommon();
|
ZygoteHooks.postForkCommon();
|
||||||
|
|
||||||
|
Log.i("zygote",
|
||||||
|
"Filled the USAP pool. New USAPs: " + numUsapsToSpawn);
|
||||||
|
}
|
||||||
|
|
||||||
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -397,7 +358,7 @@ class ZygoteServer {
|
|||||||
mUsapPoolEnabled = newStatus;
|
mUsapPoolEnabled = newStatus;
|
||||||
|
|
||||||
if (newStatus) {
|
if (newStatus) {
|
||||||
return fillUsapPool(new int[]{ sessionSocket.getFileDescriptor().getInt$() }, false);
|
return fillUsapPool(new int[]{ sessionSocket.getFileDescriptor().getInt$() });
|
||||||
} else {
|
} else {
|
||||||
Zygote.emptyUsapPool();
|
Zygote.emptyUsapPool();
|
||||||
return null;
|
return null;
|
||||||
@@ -416,8 +377,6 @@ class ZygoteServer {
|
|||||||
socketFDs.add(mZygoteSocket.getFileDescriptor());
|
socketFDs.add(mZygoteSocket.getFileDescriptor());
|
||||||
peers.add(null);
|
peers.add(null);
|
||||||
|
|
||||||
long usapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
fetchUsapPoolPolicyPropsWithMinInterval();
|
fetchUsapPoolPolicyPropsWithMinInterval();
|
||||||
|
|
||||||
@@ -471,40 +430,12 @@ class ZygoteServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int pollTimeoutMs;
|
|
||||||
|
|
||||||
if (usapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
|
|
||||||
pollTimeoutMs = -1;
|
|
||||||
} else {
|
|
||||||
int elapsedTimeMs =
|
|
||||||
(int) (System.currentTimeMillis() - usapPoolRefillTriggerTimestamp);
|
|
||||||
|
|
||||||
if (elapsedTimeMs >= mUsapPoolRefillDelayMs) {
|
|
||||||
// Normalize the poll timeout value when the time between one poll event and the
|
|
||||||
// next pushes us over the delay value. This prevents poll receiving a 0
|
|
||||||
// timeout value, which would result in it returning immediately.
|
|
||||||
pollTimeoutMs = -1;
|
|
||||||
} else {
|
|
||||||
pollTimeoutMs = mUsapPoolRefillDelayMs - elapsedTimeMs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int pollReturnValue;
|
|
||||||
try {
|
try {
|
||||||
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
|
Os.poll(pollFDs, -1);
|
||||||
} catch (ErrnoException ex) {
|
} catch (ErrnoException ex) {
|
||||||
throw new RuntimeException("poll failed", ex);
|
throw new RuntimeException("poll failed", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
UsapPoolRefillAction usapPoolRefillAction = UsapPoolRefillAction.NONE;
|
|
||||||
if (pollReturnValue == 0) {
|
|
||||||
// The poll timeout has been exceeded. This only occurs when we have finished the
|
|
||||||
// USAP pool refill delay period.
|
|
||||||
|
|
||||||
usapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
|
|
||||||
usapPoolRefillAction = UsapPoolRefillAction.DELAYED;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
boolean usapPoolFDRead = false;
|
boolean usapPoolFDRead = false;
|
||||||
|
|
||||||
while (--pollIndex >= 0) {
|
while (--pollIndex >= 0) {
|
||||||
@@ -528,8 +459,8 @@ class ZygoteServer {
|
|||||||
|
|
||||||
// TODO (chriswailes): Is this extra check necessary?
|
// TODO (chriswailes): Is this extra check necessary?
|
||||||
if (mIsForkChild) {
|
if (mIsForkChild) {
|
||||||
// We're in the child. We should always have a command to run at
|
// We're in the child. We should always have a command to run at this
|
||||||
// this stage if processOneCommand hasn't called "exec".
|
// stage if processOneCommand hasn't called "exec".
|
||||||
if (command == null) {
|
if (command == null) {
|
||||||
throw new IllegalStateException("command == null");
|
throw new IllegalStateException("command == null");
|
||||||
}
|
}
|
||||||
@@ -543,8 +474,7 @@ class ZygoteServer {
|
|||||||
|
|
||||||
// We don't know whether the remote side of the socket was closed or
|
// We don't know whether the remote side of the socket was closed or
|
||||||
// not until we attempt to read from it from processOneCommand. This
|
// not until we attempt to read from it from processOneCommand. This
|
||||||
// shows up as a regular POLLIN event in our regular processing
|
// shows up as a regular POLLIN event in our regular processing loop.
|
||||||
// loop.
|
|
||||||
if (connection.isClosedByPeer()) {
|
if (connection.isClosedByPeer()) {
|
||||||
connection.closeSocket();
|
connection.closeSocket();
|
||||||
peers.remove(pollIndex);
|
peers.remove(pollIndex);
|
||||||
@@ -553,10 +483,10 @@ class ZygoteServer {
|
|||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (!mIsForkChild) {
|
if (!mIsForkChild) {
|
||||||
// We're in the server so any exception here is one that has taken
|
// We're in the server so any exception here is one that has taken place
|
||||||
// place pre-fork while processing commands or reading / writing
|
// pre-fork while processing commands or reading / writing from the
|
||||||
// from the control socket. Make a loud noise about any such
|
// control socket. Make a loud noise about any such exceptions so that
|
||||||
// exceptions so that we know exactly what failed and why.
|
// we know exactly what failed and why.
|
||||||
|
|
||||||
Slog.e(TAG, "Exception executing zygote command: ", e);
|
Slog.e(TAG, "Exception executing zygote command: ", e);
|
||||||
|
|
||||||
@@ -569,16 +499,15 @@ class ZygoteServer {
|
|||||||
socketFDs.remove(pollIndex);
|
socketFDs.remove(pollIndex);
|
||||||
} else {
|
} else {
|
||||||
// We're in the child so any exception caught here has happened post
|
// We're in the child so any exception caught here has happened post
|
||||||
// fork and before we execute ActivityThread.main (or any other
|
// fork and before we execute ActivityThread.main (or any other main()
|
||||||
// main() method). Log the details of the exception and bring down
|
// method). Log the details of the exception and bring down the process.
|
||||||
// the process.
|
|
||||||
Log.e(TAG, "Caught post-fork exception in child process.", e);
|
Log.e(TAG, "Caught post-fork exception in child process.", e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// Reset the child flag, in the event that the child process is a child-
|
// 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
|
// zygote. The flag will not be consulted this loop pass after the Runnable
|
||||||
// Runnable is returned.
|
// is returned.
|
||||||
mIsForkChild = false;
|
mIsForkChild = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -586,15 +515,12 @@ class ZygoteServer {
|
|||||||
|
|
||||||
// If this is the event FD the payload will be the number of USAPs removed.
|
// If this is the event FD the payload will be the number of USAPs removed.
|
||||||
// If this is a reporting pipe FD the payload will be the PID of the USAP
|
// If this is a reporting pipe FD the payload will be the PID of the USAP
|
||||||
// that was just specialized. The `continue` statements below ensure that
|
// that was just specialized.
|
||||||
// the messagePayload will always be valid if we complete the try block
|
long messagePayload = -1;
|
||||||
// without an exception.
|
|
||||||
long messagePayload;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
|
byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
|
||||||
int readBytes =
|
int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
|
||||||
Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
|
|
||||||
|
|
||||||
if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
|
if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
|
||||||
DataInputStream inputStream =
|
DataInputStream inputStream =
|
||||||
@@ -626,37 +552,18 @@ class ZygoteServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check to see if the USAP pool needs to be refilled.
|
||||||
if (usapPoolFDRead) {
|
if (usapPoolFDRead) {
|
||||||
int usapPoolCount = Zygote.getUsapPoolCount();
|
|
||||||
|
|
||||||
if (usapPoolCount < mUsapPoolSizeMin) {
|
|
||||||
// Immediate refill
|
|
||||||
usapPoolRefillAction = UsapPoolRefillAction.IMMEDIATE;
|
|
||||||
} else if (mUsapPoolSizeMax - usapPoolCount >= mUsapPoolRefillThreshold) {
|
|
||||||
// Delayed refill
|
|
||||||
usapPoolRefillTriggerTimestamp = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usapPoolRefillAction != UsapPoolRefillAction.NONE) {
|
|
||||||
int[] sessionSocketRawFDs =
|
int[] sessionSocketRawFDs =
|
||||||
socketFDs.subList(1, socketFDs.size())
|
socketFDs.subList(1, socketFDs.size())
|
||||||
.stream()
|
.stream()
|
||||||
.mapToInt(FileDescriptor::getInt$)
|
.mapToInt(FileDescriptor::getInt$)
|
||||||
.toArray();
|
.toArray();
|
||||||
|
|
||||||
final boolean isPriorityRefill =
|
final Runnable command = fillUsapPool(sessionSocketRawFDs);
|
||||||
usapPoolRefillAction == UsapPoolRefillAction.IMMEDIATE;
|
|
||||||
|
|
||||||
final Runnable command =
|
|
||||||
fillUsapPool(sessionSocketRawFDs, isPriorityRefill);
|
|
||||||
|
|
||||||
if (command != null) {
|
if (command != null) {
|
||||||
return command;
|
return command;
|
||||||
} else if (isPriorityRefill) {
|
|
||||||
// Schedule a delayed refill to finish refilling the pool.
|
|
||||||
usapPoolRefillTriggerTimestamp = System.currentTimeMillis();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,15 +163,6 @@ static int gUsapPoolEventFD = -1;
|
|||||||
*/
|
*/
|
||||||
static constexpr int USAP_POOL_SIZE_MAX_LIMIT = 100;
|
static constexpr int USAP_POOL_SIZE_MAX_LIMIT = 100;
|
||||||
|
|
||||||
/** The numeric value for the maximum priority a process may possess. */
|
|
||||||
static constexpr int PROCESS_PRIORITY_MAX = -20;
|
|
||||||
|
|
||||||
/** The numeric value for the minimum priority a process may possess. */
|
|
||||||
static constexpr int PROCESS_PRIORITY_MIN = 19;
|
|
||||||
|
|
||||||
/** The numeric value for the normal priority a process should have. */
|
|
||||||
static constexpr int PROCESS_PRIORITY_DEFAULT = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class containing accounting information for USAPs.
|
* A helper class containing accounting information for USAPs.
|
||||||
*/
|
*/
|
||||||
@@ -896,8 +887,7 @@ static void ClearUsapTable() {
|
|||||||
// Utility routine to fork a process from the zygote.
|
// Utility routine to fork a process from the zygote.
|
||||||
static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
|
static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
|
||||||
const std::vector<int>& fds_to_close,
|
const std::vector<int>& fds_to_close,
|
||||||
const std::vector<int>& fds_to_ignore,
|
const std::vector<int>& fds_to_ignore) {
|
||||||
bool is_priority_fork) {
|
|
||||||
SetSignalHandlers();
|
SetSignalHandlers();
|
||||||
|
|
||||||
// Curry a failure function.
|
// Curry a failure function.
|
||||||
@@ -930,12 +920,6 @@ static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
|
|||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
if (is_priority_fork) {
|
|
||||||
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
|
|
||||||
} else {
|
|
||||||
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The child process.
|
// The child process.
|
||||||
PreApplicationInit();
|
PreApplicationInit();
|
||||||
|
|
||||||
@@ -1133,9 +1117,6 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
|
|||||||
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);
|
||||||
|
|
||||||
// Reset the process priority to the default value.
|
|
||||||
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);
|
|
||||||
|
|
||||||
if (env->ExceptionCheck()) {
|
if (env->ExceptionCheck()) {
|
||||||
fail_fn("Error calling post fork hooks.");
|
fail_fn("Error calling post fork hooks.");
|
||||||
}
|
}
|
||||||
@@ -1387,7 +1368,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
|
|||||||
fds_to_ignore.push_back(gUsapPoolEventFD);
|
fds_to_ignore.push_back(gUsapPoolEventFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
|
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
|
||||||
@@ -1414,8 +1395,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
|
|||||||
|
|
||||||
pid_t pid = ForkCommon(env, true,
|
pid_t pid = ForkCommon(env, true,
|
||||||
fds_to_close,
|
fds_to_close,
|
||||||
fds_to_ignore,
|
fds_to_ignore);
|
||||||
true);
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
|
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
|
||||||
permitted_capabilities, effective_capabilities,
|
permitted_capabilities, effective_capabilities,
|
||||||
@@ -1457,15 +1437,13 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
|
|||||||
* zygote in managed code.
|
* zygote in managed code.
|
||||||
* @param managed_session_socket_fds A list of anonymous session sockets that must be ignored by
|
* @param managed_session_socket_fds A list of anonymous session sockets that must be ignored by
|
||||||
* the FD hygiene code and automatically "closed" in the new USAP.
|
* the FD hygiene code and automatically "closed" in the new USAP.
|
||||||
* @param is_priority_fork Controls the nice level assigned to the newly created process
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env,
|
static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env,
|
||||||
jclass,
|
jclass,
|
||||||
jint read_pipe_fd,
|
jint read_pipe_fd,
|
||||||
jint write_pipe_fd,
|
jint write_pipe_fd,
|
||||||
jintArray managed_session_socket_fds,
|
jintArray managed_session_socket_fds) {
|
||||||
jboolean is_priority_fork) {
|
|
||||||
std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
|
std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
|
||||||
fds_to_ignore(fds_to_close);
|
fds_to_ignore(fds_to_close);
|
||||||
|
|
||||||
@@ -1487,8 +1465,7 @@ static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env,
|
|||||||
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());
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (usap_pid != 0) {
|
if (usap_pid != 0) {
|
||||||
++gUsapPoolCount;
|
++gUsapPoolCount;
|
||||||
@@ -1692,10 +1669,6 @@ static jboolean com_android_internal_os_Zygote_nativeDisableExecuteOnly(JNIEnv*
|
|||||||
return dl_iterate_phdr(DisableExecuteOnly, nullptr) == 0;
|
return dl_iterate_phdr(DisableExecuteOnly, nullptr) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void com_android_internal_os_Zygote_nativeBoostUsapPriority(JNIEnv* env, jclass) {
|
|
||||||
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
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",
|
||||||
@@ -1708,7 +1681,7 @@ static const JNINativeMethod gMethods[] = {
|
|||||||
(void *) com_android_internal_os_Zygote_nativePreApplicationInit },
|
(void *) com_android_internal_os_Zygote_nativePreApplicationInit },
|
||||||
{ "nativeInstallSeccompUidGidFilter", "(II)V",
|
{ "nativeInstallSeccompUidGidFilter", "(II)V",
|
||||||
(void *) com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter },
|
(void *) com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter },
|
||||||
{ "nativeForkUsap", "(II[IZ)I",
|
{ "nativeForkUsap", "(II[I)I",
|
||||||
(void *) com_android_internal_os_Zygote_nativeForkUsap },
|
(void *) com_android_internal_os_Zygote_nativeForkUsap },
|
||||||
{ "nativeSpecializeAppProcess",
|
{ "nativeSpecializeAppProcess",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V",
|
||||||
@@ -1726,9 +1699,7 @@ static const JNINativeMethod gMethods[] = {
|
|||||||
{ "nativeEmptyUsapPool", "()V",
|
{ "nativeEmptyUsapPool", "()V",
|
||||||
(void *) com_android_internal_os_Zygote_nativeEmptyUsapPool },
|
(void *) com_android_internal_os_Zygote_nativeEmptyUsapPool },
|
||||||
{ "nativeDisableExecuteOnly", "()Z",
|
{ "nativeDisableExecuteOnly", "()Z",
|
||||||
(void *) com_android_internal_os_Zygote_nativeDisableExecuteOnly },
|
(void *) com_android_internal_os_Zygote_nativeDisableExecuteOnly }
|
||||||
{ "nativeBoostUsapPriority", "()V",
|
|
||||||
(void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int register_com_android_internal_os_Zygote(JNIEnv* env) {
|
int register_com_android_internal_os_Zygote(JNIEnv* env) {
|
||||||
|
|||||||
Reference in New Issue
Block a user