libprocessgroup: Handle temporarily non-empty group removal failure

Cgroup removal fails with EBUSY if there are active processes or threads
still alive in the cgroup. Occasionally a thread or a process might be
stuck in an interruptible sleep and take some time during exit. In such
cases attempts to remove the cgroup it belongs to will fail. This
results in occasional leftover cgroups. These empty unused cgroups
consume memory.
Ensure RemoveProcessGroup always retries and increase the retries to
keep trying for 2 secs before giving up. In majority of cases only a few
retries are needed but in rare cases a thread can be blocked for longer
time, therefore the number of retries is set large enough to cover them.

Bug: 233319780
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Change-Id: I2e4bb1f7b7e19c904c85faea7bbabbfdef9c8125
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 267e62c..51c810e 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -187,10 +187,6 @@
     auto uid_pid_path = ConvertUidPidToPath(cgroup, uid, pid);
     auto uid_path = ConvertUidToPath(cgroup, uid);
 
-    if (retries == 0) {
-        retries = 1;
-    }
-
     while (retries--) {
         ret = rmdir(uid_pid_path.c_str());
         if (!ret || errno != EBUSY) break;
@@ -463,12 +459,13 @@
                       << " in " << static_cast<int>(ms) << "ms";
         }
 
-        int err = RemoveProcessGroup(cgroup, uid, initialPid, retries);
+        // 400 retries correspond to 2 secs max timeout
+        int err = RemoveProcessGroup(cgroup, uid, initialPid, 400);
 
         if (isMemoryCgroupSupported() && UsePerAppMemcg()) {
             std::string memcg_apps_path;
             if (CgroupGetMemcgAppsPath(&memcg_apps_path) &&
-                RemoveProcessGroup(memcg_apps_path.c_str(), uid, initialPid, retries) < 0) {
+                RemoveProcessGroup(memcg_apps_path.c_str(), uid, initialPid, 400) < 0) {
                 return -1;
             }
         }