From 6c4c4a5927c5b7519047e7f4a7cad81991e15b85 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 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 35e390f57120b..db9822d409504 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -1485,6 +1485,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 afae623cd2176..bae249f6f1e12 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -45,6 +45,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; @@ -1182,8 +1183,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; }