use process groups for processes started by init

Put every service into a process group, kill the process group
and all child processes created within the group when killing the
service. Removed libutil dependency in libprocessgroup.

Bug: 25355957
Change-Id: Ieed60ec41579f638ab9b1e66a7e6330ed578ab05
Signed-off-by: Collin Mulliner <collinrm@squareup.com>
diff --git a/init/Android.mk b/init/Android.mk
index e1a3638..7aa3c3f 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -52,7 +52,7 @@
     service.cpp \
     util.cpp \
 
-LOCAL_STATIC_LIBRARIES := libbase libselinux
+LOCAL_STATIC_LIBRARIES := libbase libselinux liblog libprocessgroup
 LOCAL_MODULE := libinit
 LOCAL_SANITIZE := integer
 LOCAL_CLANG := true
@@ -91,7 +91,6 @@
     libcutils \
     libbase \
     libext4_utils_static \
-    libutils \
     libc \
     libselinux \
     liblog \
@@ -100,7 +99,8 @@
     libc++_static \
     libdl \
     libsparse_static \
-    libz
+    libz \
+    libprocessgroup
 
 # Create symlinks
 LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
diff --git a/init/service.cpp b/init/service.cpp
index f5b8b00..4175d05 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -30,6 +30,8 @@
 #include <cutils/android_reboot.h>
 #include <cutils/sockets.h>
 
+#include <processgroup/processgroup.h>
+
 #include "action.h"
 #include "init.h"
 #include "init_parser.h"
@@ -97,7 +99,7 @@
     if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
         NOTICE("Service '%s' (pid %d) killing any children in process group\n",
                name_.c_str(), pid_);
-        kill(-pid_, SIGKILL);
+        killProcessGroup(uid_, pid_, SIGKILL);
     }
 
     // Remove any sockets we may have created.
@@ -490,6 +492,7 @@
     time_started_ = gettime();
     pid_ = pid;
     flags_ |= SVC_RUNNING;
+    createProcessGroup(uid_, pid_);
 
     if ((flags_ & SVC_EXEC) != 0) {
         INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n",
@@ -532,7 +535,7 @@
     if (pid_) {
         NOTICE("Sending SIGTERM to service '%s' (pid %d)...\n", name_.c_str(),
                pid_);
-        kill(-pid_, SIGTERM);
+        killProcessGroup(uid_, pid_, SIGTERM);
         NotifyStateChange("stopping");
     }
 }
@@ -583,7 +586,7 @@
 
     if (pid_) {
         NOTICE("Service '%s' is being killed...\n", name_.c_str());
-        kill(-pid_, SIGKILL);
+        killProcessGroup(uid_, pid_, SIGKILL);
         NotifyStateChange("stopping");
     } else {
         NotifyStateChange("stopped");
diff --git a/libprocessgroup/Android.mk b/libprocessgroup/Android.mk
index ee6ba58..87985d4 100644
--- a/libprocessgroup/Android.mk
+++ b/libprocessgroup/Android.mk
@@ -3,7 +3,16 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := processgroup.cpp
 LOCAL_MODULE := libprocessgroup
-LOCAL_SHARED_LIBRARIES := liblog libutils
+LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := processgroup.cpp
+LOCAL_MODULE := libprocessgroup
+LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_CFLAGS := -Wall -Werror
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 00a0357..da4bb71 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -22,19 +22,18 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+
+#include <chrono>
 #include <memory>
 
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
 
-#include <utils/SystemClock.h>
-
 #include <processgroup/processgroup.h>
 #include "processgroup_priv.h"
 
@@ -250,25 +249,26 @@
 
 int killProcessGroup(uid_t uid, int initialPid, int signal)
 {
-    int processes;
-    const int sleep_us = 5 * 1000;  // 5ms
-    int64_t startTime = android::uptimeMillis();
-    int retry = 40;
+    std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
 
+    int retry = 40;
+    int processes;
     while ((processes = killProcessGroupOnce(uid, initialPid, signal)) > 0) {
         SLOGV("killed %d processes for processgroup %d\n", processes, initialPid);
         if (retry > 0) {
-            usleep(sleep_us);
+            usleep(5 * 1000); // 5ms
             --retry;
         } else {
-            SLOGE("failed to kill %d processes for processgroup %d\n",
-                    processes, initialPid);
+            SLOGE("failed to kill %d processes for processgroup %d\n", processes, initialPid);
             break;
         }
     }
 
-    SLOGV("Killed process group uid %d pid %d in %" PRId64 "ms, %d procs remain", uid, initialPid,
-            android::uptimeMillis()-startTime, processes);
+    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
+
+    SLOGV("Killed process group uid %d pid %d in %dms, %d procs remain", uid, initialPid,
+          static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()),
+          processes);
 
     if (processes == 0) {
         return removeProcessGroup(uid, initialPid);