diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/com/android/internal/os/Zygote.java | 150 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/ZygoteConnection.java | 3 |
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."); } } |
