summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/com/android/internal/os/Zygote.java150
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java3
2 files changed, 94 insertions, 59 deletions
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 2736c6a7149f..ee81868da25b 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -519,6 +519,9 @@ public final class Zygote {
try {
sessionSocket = usapPoolSocket.accept();
+ // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
+ blockSigTerm();
+
BufferedReader usapReader =
new BufferedReader(new InputStreamReader(sessionSocket.getInputStream()));
usapOutputStream =
@@ -537,87 +540,116 @@ public final class Zygote {
} else {
Log.e("USAP", "Truncated command received.");
IoUtils.closeQuietly(sessionSocket);
+
+ // Re-enable SIGTERM so the USAP can be flushed from the pool if necessary.
+ unblockSigTerm();
}
} catch (Exception ex) {
Log.e("USAP", ex.getMessage());
IoUtils.closeQuietly(sessionSocket);
+
+ // Re-enable SIGTERM so the USAP can be flushed from the pool if necessary.
+ unblockSigTerm();
}
}
- applyUidSecurityPolicy(args, peerCredentials);
- applyDebuggerSystemProperty(args);
+ try {
+ // SIGTERM is blocked on loop exit. This prevents a USAP that is specializing from
+ // being killed during a pool flush.
- int[][] rlimits = null;
+ applyUidSecurityPolicy(args, peerCredentials);
+ applyDebuggerSystemProperty(args);
- if (args.mRLimits != null) {
- rlimits = args.mRLimits.toArray(INT_ARRAY_2D);
- }
+ int[][] rlimits = null;
- // This must happen before the SELinux policy for this process is
- // changed when specializing.
- try {
- // Used by ZygoteProcess.zygoteSendArgsAndGetResult to fill in a
- // Process.ProcessStartResult object.
- usapOutputStream.writeInt(pid);
- } catch (IOException ioEx) {
- Log.e("USAP", "Failed to write response to session socket: " + ioEx.getMessage());
- System.exit(-1);
- } finally {
- IoUtils.closeQuietly(sessionSocket);
+ if (args.mRLimits != null) {
+ rlimits = args.mRLimits.toArray(INT_ARRAY_2D);
+ }
+ // This must happen before the SELinux policy for this process is
+ // changed when specializing.
try {
- // This socket is closed using Os.close due to an issue with the implementation of
- // LocalSocketImp.close. Because the raw FD is created by init and then loaded from
- // an environment variable (as opposed to being created by the LocalSocketImpl
- // itself) the current implementation will not actually close the underlying FD.
- //
- // See b/130309968 for discussion of this issue.
- Os.close(usapPoolSocket.getFileDescriptor());
- } catch (ErrnoException ex) {
- Log.e("USAP", "Failed to close USAP pool socket: " + ex.getMessage());
+ // Used by ZygoteProcess.zygoteSendArgsAndGetResult to fill in a
+ // Process.ProcessStartResult object.
+ usapOutputStream.writeInt(pid);
+ } catch (IOException ioEx) {
+ Log.e("USAP", "Failed to write response to session socket: "
+ + ioEx.getMessage());
+ throw new RuntimeException(ioEx);
+ } finally {
+ IoUtils.closeQuietly(sessionSocket);
+
+ try {
+ // This socket is closed using Os.close due to an issue with the implementation
+ // of LocalSocketImp.close(). Because the raw FD is created by init and then
+ // loaded from an environment variable (as opposed to being created by the
+ // LocalSocketImpl itself) the current implementation will not actually close
+ // the underlying FD.
+ //
+ // See b/130309968 for discussion of this issue.
+ Os.close(usapPoolSocket.getFileDescriptor());
+ } catch (ErrnoException ex) {
+ Log.e("USAP", "Failed to close USAP pool socket");
+ throw new RuntimeException(ex);
+ }
}
- }
- try {
- ByteArrayOutputStream buffer =
- new ByteArrayOutputStream(Zygote.USAP_MANAGEMENT_MESSAGE_BYTES);
- DataOutputStream outputStream = new DataOutputStream(buffer);
-
- // This is written as a long so that the USAP reporting pipe and USAP pool event FD
- // handlers in ZygoteServer.runSelectLoop can be unified. These two cases should both
- // send/receive 8 bytes.
- outputStream.writeLong(pid);
- outputStream.flush();
-
- Os.write(writePipe, buffer.toByteArray(), 0, buffer.size());
- } catch (Exception ex) {
- Log.e("USAP",
- String.format("Failed to write PID (%d) to pipe (%d): %s",
- pid, writePipe.getInt$(), ex.getMessage()));
- System.exit(-1);
- } finally {
- IoUtils.closeQuietly(writePipe);
- }
+ try {
+ ByteArrayOutputStream buffer =
+ new ByteArrayOutputStream(Zygote.USAP_MANAGEMENT_MESSAGE_BYTES);
+ DataOutputStream outputStream = new DataOutputStream(buffer);
+
+ // This is written as a long so that the USAP reporting pipe and USAP pool event FD
+ // handlers in ZygoteServer.runSelectLoop can be unified. These two cases should
+ // both send/receive 8 bytes.
+ outputStream.writeLong(pid);
+ outputStream.flush();
+
+ Os.write(writePipe, buffer.toByteArray(), 0, buffer.size());
+ } catch (Exception ex) {
+ Log.e("USAP",
+ String.format("Failed to write PID (%d) to pipe (%d): %s",
+ pid, writePipe.getInt$(), ex.getMessage()));
+ throw new RuntimeException(ex);
+ } finally {
+ IoUtils.closeQuietly(writePipe);
+ }
+
+ specializeAppProcess(args.mUid, args.mGid, args.mGids,
+ args.mRuntimeFlags, rlimits, args.mMountExternal,
+ args.mSeInfo, args.mNiceName, args.mStartChildZygote,
+ args.mInstructionSet, args.mAppDataDir);
- specializeAppProcess(args.mUid, args.mGid, args.mGids,
- args.mRuntimeFlags, rlimits, args.mMountExternal,
- args.mSeInfo, args.mNiceName, args.mStartChildZygote,
- args.mInstructionSet, args.mAppDataDir);
+ disableExecuteOnly(args.mTargetSdkVersion);
- disableExecuteOnly(args.mTargetSdkVersion);
+ if (args.mNiceName != null) {
+ Process.setArgV0(args.mNiceName);
+ }
+
+ // End of the postFork event.
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- if (args.mNiceName != null) {
- Process.setArgV0(args.mNiceName);
+ return ZygoteInit.zygoteInit(args.mTargetSdkVersion,
+ args.mRemainingArgs,
+ null /* classLoader */);
+ } finally {
+ // Unblock SIGTERM to restore the process to default behavior.
+ unblockSigTerm();
}
+ }
- // End of the postFork event.
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ private static void blockSigTerm() {
+ nativeBlockSigTerm();
+ }
+
+ private static native void nativeBlockSigTerm();
- return ZygoteInit.zygoteInit(args.mTargetSdkVersion,
- args.mRemainingArgs,
- null /* classLoader */);
+ private static void unblockSigTerm() {
+ nativeUnblockSigTerm();
}
+ private static native void nativeUnblockSigTerm();
+
private static final String USAP_ERROR_PREFIX = "Invalid command to USAP: ";
/**
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 785256eb6351..e556dd4d8243 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -338,6 +338,7 @@ class ZygoteConnection {
Runnable stateChangeCode) {
try {
if (zygoteServer.isUsapPoolEnabled()) {
+ Log.i(TAG, "Emptying USAP Pool due to state change.");
Zygote.emptyUsapPool();
}
@@ -351,6 +352,8 @@ class ZygoteConnection {
if (fpResult != null) {
zygoteServer.setForkChild();
return fpResult;
+ } else {
+ Log.i(TAG, "Finished refilling USAP Pool after state change.");
}
}