Loading init/service.cpp +24 −4 Original line number Diff line number Diff line Loading @@ -42,9 +42,11 @@ #if defined(__ANDROID__) #include <ApexProperties.sysprop.h> #include <android/api-level.h> #include "mount_namespace.h" #include "property_service.h" #include "selinux.h" #else #include "host_init_stubs.h" #endif Loading Loading @@ -182,7 +184,7 @@ void Service::NotifyStateChange(const std::string& new_state) const { } } void Service::KillProcessGroup(int signal) { void Service::KillProcessGroup(int signal, bool report_oneshot) { // If we've already seen a successful result from killProcessGroup*(), then we have removed // the cgroup already and calling these functions a second time will simply result in an error. // This is true regardless of which signal was sent. Loading @@ -190,11 +192,20 @@ void Service::KillProcessGroup(int signal) { if (!process_cgroup_empty_) { LOG(INFO) << "Sending signal " << signal << " to service '" << name_ << "' (pid " << pid_ << ") process group..."; int max_processes = 0; int r; if (signal == SIGTERM) { r = killProcessGroupOnce(proc_attr_.uid, pid_, signal); r = killProcessGroupOnce(proc_attr_.uid, pid_, signal, &max_processes); } else { r = killProcessGroup(proc_attr_.uid, pid_, signal); r = killProcessGroup(proc_attr_.uid, pid_, signal, &max_processes); } if (report_oneshot && max_processes > 0) { LOG(WARNING) << "Killed " << max_processes << " additional processes from a oneshot process group for service '" << name_ << "'. This is new behavior, previously child processes would not be killed in " "this case."; } if (r == 0) process_cgroup_empty_ = true; Loading Loading @@ -244,7 +255,16 @@ void Service::SetProcessAttributesAndCaps() { void Service::Reap(const siginfo_t& siginfo) { if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) { KillProcessGroup(SIGKILL); KillProcessGroup(SIGKILL, false); } else { // Legacy behavior from ~2007 until Android R: this else branch did not exist and we did not // kill the process group in this case. if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) { // The new behavior in Android R is to kill these process groups in all cases. The // 'true' parameter instructions KillProcessGroup() to report a warning message where it // detects a difference in behavior has occurred. KillProcessGroup(SIGKILL, true); } } // Remove any socket resources we may have created. Loading init/service.h +1 −1 Original line number Diff line number Diff line Loading @@ -132,7 +132,7 @@ class Service { private: void NotifyStateChange(const std::string& new_state) const; void StopOrReset(int how); void KillProcessGroup(int signal); void KillProcessGroup(int signal, bool report_oneshot = false); void SetProcessAttributesAndCaps(); static unsigned long next_start_order_; Loading libprocessgroup/include/processgroup/processgroup.h +5 −2 Original line number Diff line number Diff line Loading @@ -47,11 +47,14 @@ void DropTaskProfilesResourceCaching(); // Return 0 and removes the cgroup if there are no longer any processes in it. // Returns -1 in the case of an error occurring or if there are processes still running // even after retrying for up to 200ms. int killProcessGroup(uid_t uid, int initialPid, int signal); // If max_processes is not nullptr, it returns the maximum number of processes seen in the cgroup // during the killing process. Note that this can be 0 if all processes from the process group have // already been terminated. int killProcessGroup(uid_t uid, int initialPid, int signal, int* max_processes = nullptr); // Returns the same as killProcessGroup(), however it does not retry, which means // that it only returns 0 in the case that the cgroup exists and it contains no processes. int killProcessGroupOnce(uid_t uid, int initialPid, int signal); int killProcessGroupOnce(uid_t uid, int initialPid, int signal, int* max_processes = nullptr); int createProcessGroup(uid_t uid, int initialPid, bool memControl = false); Loading libprocessgroup/processgroup.cpp +13 −5 Original line number Diff line number Diff line Loading @@ -301,7 +301,8 @@ static int DoKillProcessGroupOnce(const char* cgroup, uid_t uid, int initialPid, return feof(fd.get()) ? processes : -1; } static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) { static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries, int* max_processes) { std::string cpuacct_path; std::string memory_path; Loading @@ -316,9 +317,16 @@ static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); if (max_processes != nullptr) { *max_processes = 0; } int retry = retries; int processes; while ((processes = DoKillProcessGroupOnce(cgroup, uid, initialPid, signal)) > 0) { if (max_processes != nullptr && processes > *max_processes) { *max_processes = processes; } LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid; if (retry > 0) { std::this_thread::sleep_for(5ms); Loading Loading @@ -359,12 +367,12 @@ static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) } } int killProcessGroup(uid_t uid, int initialPid, int signal) { return KillProcessGroup(uid, initialPid, signal, 40 /*retries*/); int killProcessGroup(uid_t uid, int initialPid, int signal, int* max_processes) { return KillProcessGroup(uid, initialPid, signal, 40 /*retries*/, max_processes); } int killProcessGroupOnce(uid_t uid, int initialPid, int signal) { return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/); int killProcessGroupOnce(uid_t uid, int initialPid, int signal, int* max_processes) { return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/, max_processes); } int createProcessGroup(uid_t uid, int initialPid, bool memControl) { Loading Loading
init/service.cpp +24 −4 Original line number Diff line number Diff line Loading @@ -42,9 +42,11 @@ #if defined(__ANDROID__) #include <ApexProperties.sysprop.h> #include <android/api-level.h> #include "mount_namespace.h" #include "property_service.h" #include "selinux.h" #else #include "host_init_stubs.h" #endif Loading Loading @@ -182,7 +184,7 @@ void Service::NotifyStateChange(const std::string& new_state) const { } } void Service::KillProcessGroup(int signal) { void Service::KillProcessGroup(int signal, bool report_oneshot) { // If we've already seen a successful result from killProcessGroup*(), then we have removed // the cgroup already and calling these functions a second time will simply result in an error. // This is true regardless of which signal was sent. Loading @@ -190,11 +192,20 @@ void Service::KillProcessGroup(int signal) { if (!process_cgroup_empty_) { LOG(INFO) << "Sending signal " << signal << " to service '" << name_ << "' (pid " << pid_ << ") process group..."; int max_processes = 0; int r; if (signal == SIGTERM) { r = killProcessGroupOnce(proc_attr_.uid, pid_, signal); r = killProcessGroupOnce(proc_attr_.uid, pid_, signal, &max_processes); } else { r = killProcessGroup(proc_attr_.uid, pid_, signal); r = killProcessGroup(proc_attr_.uid, pid_, signal, &max_processes); } if (report_oneshot && max_processes > 0) { LOG(WARNING) << "Killed " << max_processes << " additional processes from a oneshot process group for service '" << name_ << "'. This is new behavior, previously child processes would not be killed in " "this case."; } if (r == 0) process_cgroup_empty_ = true; Loading Loading @@ -244,7 +255,16 @@ void Service::SetProcessAttributesAndCaps() { void Service::Reap(const siginfo_t& siginfo) { if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) { KillProcessGroup(SIGKILL); KillProcessGroup(SIGKILL, false); } else { // Legacy behavior from ~2007 until Android R: this else branch did not exist and we did not // kill the process group in this case. if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) { // The new behavior in Android R is to kill these process groups in all cases. The // 'true' parameter instructions KillProcessGroup() to report a warning message where it // detects a difference in behavior has occurred. KillProcessGroup(SIGKILL, true); } } // Remove any socket resources we may have created. Loading
init/service.h +1 −1 Original line number Diff line number Diff line Loading @@ -132,7 +132,7 @@ class Service { private: void NotifyStateChange(const std::string& new_state) const; void StopOrReset(int how); void KillProcessGroup(int signal); void KillProcessGroup(int signal, bool report_oneshot = false); void SetProcessAttributesAndCaps(); static unsigned long next_start_order_; Loading
libprocessgroup/include/processgroup/processgroup.h +5 −2 Original line number Diff line number Diff line Loading @@ -47,11 +47,14 @@ void DropTaskProfilesResourceCaching(); // Return 0 and removes the cgroup if there are no longer any processes in it. // Returns -1 in the case of an error occurring or if there are processes still running // even after retrying for up to 200ms. int killProcessGroup(uid_t uid, int initialPid, int signal); // If max_processes is not nullptr, it returns the maximum number of processes seen in the cgroup // during the killing process. Note that this can be 0 if all processes from the process group have // already been terminated. int killProcessGroup(uid_t uid, int initialPid, int signal, int* max_processes = nullptr); // Returns the same as killProcessGroup(), however it does not retry, which means // that it only returns 0 in the case that the cgroup exists and it contains no processes. int killProcessGroupOnce(uid_t uid, int initialPid, int signal); int killProcessGroupOnce(uid_t uid, int initialPid, int signal, int* max_processes = nullptr); int createProcessGroup(uid_t uid, int initialPid, bool memControl = false); Loading
libprocessgroup/processgroup.cpp +13 −5 Original line number Diff line number Diff line Loading @@ -301,7 +301,8 @@ static int DoKillProcessGroupOnce(const char* cgroup, uid_t uid, int initialPid, return feof(fd.get()) ? processes : -1; } static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) { static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries, int* max_processes) { std::string cpuacct_path; std::string memory_path; Loading @@ -316,9 +317,16 @@ static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); if (max_processes != nullptr) { *max_processes = 0; } int retry = retries; int processes; while ((processes = DoKillProcessGroupOnce(cgroup, uid, initialPid, signal)) > 0) { if (max_processes != nullptr && processes > *max_processes) { *max_processes = processes; } LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid; if (retry > 0) { std::this_thread::sleep_for(5ms); Loading Loading @@ -359,12 +367,12 @@ static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) } } int killProcessGroup(uid_t uid, int initialPid, int signal) { return KillProcessGroup(uid, initialPid, signal, 40 /*retries*/); int killProcessGroup(uid_t uid, int initialPid, int signal, int* max_processes) { return KillProcessGroup(uid, initialPid, signal, 40 /*retries*/, max_processes); } int killProcessGroupOnce(uid_t uid, int initialPid, int signal) { return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/); int killProcessGroupOnce(uid_t uid, int initialPid, int signal, int* max_processes) { return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/, max_processes); } int createProcessGroup(uid_t uid, int initialPid, bool memControl) { Loading