From b8577ee7fcbd8d3aefdde535f2838405bdbd85d2 Mon Sep 17 00:00:00 2001 From: "T.J. Mercier" Date: Mon, 3 Apr 2023 20:20:39 +0000 Subject: [PATCH] Don't wait after SIGKILL when freeze-killing When freeze-killing (for package force-stops) we attempt to wait until all processes have 1) Received the kill signal AND 2) have actually exited and been cleaned up AND 3) the associated cgroup(s) have been removed. The second and third parts can take a long time, which can lead to lock contention in ActivityManagerService when many kills are attempted simultaneously. For freeze-kills with SIGKILL we do not need to wait to prevent app-restart exploits. Now we send these processes a SIGKILL after freezing, but do not wait until they are actually dead before returning. Bug: 274646058 Test: Force-stop of chrome with 15 tabs completes ~500ms faster Test: Full Play store update causes no ANR (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6c4c4a5927c5b7519047e7f4a7cad81991e15b85) Merged-In: Ib4cc2e31190338b565e4a89acce64d9ae52b19c9 Change-Id: Ib4cc2e31190338b565e4a89acce64d9ae52b19c9 --- core/java/android/os/Process.java | 9 +++++++++ core/jni/android_util_Process.cpp | 6 ++++++ .../core/java/com/android/server/am/ProcessRecord.java | 5 +++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index b2208d19d9eeb..bf3d52d358ede 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -1498,6 +1498,15 @@ public class Process { */ public static final native int killProcessGroup(int uid, int pid); + /** + * Send a signal to all processes in a group under the given PID, but do not wait for the + * processes to be fully cleaned up, or for the cgroup to be removed before returning. + * Callers should also ensure that killProcessGroup is called later to ensure the cgroup is + * fully removed, otherwise system resources may leak. + * @hide + */ + public static final native int sendSignalToProcessGroup(int uid, int pid, int signal); + /** * Freeze the cgroup for the given UID. * This cgroup may contain child cgroups which will also be frozen. If this cgroup or its diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 9501c8d49e53d..4f2bf4a4f6cb5 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -1238,6 +1238,11 @@ jint android_os_Process_killProcessGroup(JNIEnv* env, jobject clazz, jint uid, j return killProcessGroup(uid, pid, SIGKILL); } +jint android_os_Process_sendSignalToProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid, + jint signal) { + return sendSignalToProcessGroup(uid, pid, signal); +} + void android_os_Process_removeAllProcessGroups(JNIEnv* env, jobject clazz) { return removeAllProcessGroups(); @@ -1305,6 +1310,7 @@ static const JNINativeMethod methods[] = { //{"setApplicationObject", "(Landroid/os/IBinder;)V", //(void*)android_os_Process_setApplicationObject}, {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup}, + {"sendSignalToProcessGroup", "(III)I", (void*)android_os_Process_sendSignalToProcessGroup}, {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups}, {"nativePidFdOpen", "(II)I", (void*)android_os_Process_nativePidFdOpen}, {"freezeCgroupUid", "(IZ)V", (void*)android_os_Process_freezeCgroupUID}, diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index ffb40ee959a49..438a08c44ef4c 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -47,6 +47,7 @@ import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.server.ServerProtoEnums; +import android.system.OsConstants; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DebugUtils; @@ -1186,8 +1187,8 @@ class ProcessRecord implements WindowProcessListener { EventLog.writeEvent(EventLogTags.AM_KILL, userId, mPid, processName, mState.getSetAdj(), reason); Process.killProcessQuiet(mPid); - if (asyncKPG) ProcessList.killProcessGroup(uid, mPid); - else Process.killProcessGroup(uid, mPid); + if (!asyncKPG) Process.sendSignalToProcessGroup(uid, mPid, OsConstants.SIGKILL); + ProcessList.killProcessGroup(uid, mPid); } else { mPendingStart = false; }