Loading init/README.md +12 −0 Original line number Diff line number Diff line Loading @@ -260,6 +260,18 @@ runs the service. > Sets the child's /proc/self/oom\_score\_adj to the specified value, which must range from -1000 to 1000. `memcg.swappiness <value>` > Sets the child's memory.swappiness to the specified value (only if memcg is mounted), which must be equal or greater than 0. `memcg.soft_limit_in_bytes <value>` > Sets the child's memory.soft_limit_in_bytes to the specified value (only if memcg is mounted), which must be equal or greater than 0. `memcg.limit_in_bytes <value>` > Sets the child's memory.limit_in_bytes to the specified value (only if memcg is mounted), which must be equal or greater than 0. `shutdown <shutdown_behavior>` > Set shutdown behavior of the service process. When this is not specified, the service is killed during shutdown process by using SIGTERM and SIGKILL. Loading init/service.cpp +54 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,9 @@ Service::Service(const std::string& name, const std::vector<std::string>& args) ioprio_pri_(0), priority_(0), oom_score_adjust_(-1000), swappiness_(-1), soft_limit_in_bytes_(-1), limit_in_bytes_(-1), args_(args) { onrestart_.InitSingleTrigger("onrestart"); } Loading @@ -196,6 +199,9 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, ioprio_pri_(0), priority_(0), oom_score_adjust_(-1000), swappiness_(-1), soft_limit_in_bytes_(-1), limit_in_bytes_(-1), args_(args) { onrestart_.InitSingleTrigger("onrestart"); } Loading Loading @@ -491,6 +497,30 @@ bool Service::ParseOomScoreAdjust(const std::vector<std::string>& args, std::str return true; } bool Service::ParseMemcgSwappiness(const std::vector<std::string>& args, std::string* err) { if (!ParseInt(args[1], &swappiness_, 0)) { *err = "swappiness value must be equal or greater than 0"; return false; } return true; } bool Service::ParseMemcgLimitInBytes(const std::vector<std::string>& args, std::string* err) { if (!ParseInt(args[1], &limit_in_bytes_, 0)) { *err = "limit_in_bytes value must be equal or greater than 0"; return false; } return true; } bool Service::ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args, std::string* err) { if (!ParseInt(args[1], &soft_limit_in_bytes_, 0)) { *err = "soft_limit_in_bytes value must be equal or greater than 0"; return false; } return true; } bool Service::ParseSeclabel(const std::vector<std::string>& args, std::string* err) { seclabel_ = args[1]; return true; Loading Loading @@ -609,6 +639,12 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const { {"onrestart", {1, kMax, &Service::ParseOnrestart}}, {"oom_score_adjust", {1, 1, &Service::ParseOomScoreAdjust}}, {"memcg.swappiness", {1, 1, &Service::ParseMemcgSwappiness}}, {"memcg.soft_limit_in_bytes", {1, 1, &Service::ParseMemcgSoftLimitInBytes}}, {"memcg.limit_in_bytes", {1, 1, &Service::ParseMemcgLimitInBytes}}, {"namespace", {1, 2, &Service::ParseNamespace}}, {"seclabel", {1, 1, &Service::ParseSeclabel}}, {"setenv", {2, 2, &Service::ParseSetenv}}, Loading Loading @@ -795,6 +831,24 @@ bool Service::Start() { if (errno != 0) { PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '" << name_ << "'"; } else { if (swappiness_ != -1) { if (!setProcessGroupSwappiness(uid_, pid_, swappiness_)) { PLOG(ERROR) << "setProcessGroupSwappiness failed"; } } if (soft_limit_in_bytes_ != -1) { if (!setProcessGroupSoftLimit(uid_, pid_, soft_limit_in_bytes_)) { PLOG(ERROR) << "setProcessGroupSoftLimit failed"; } } if (limit_in_bytes_ != -1) { if (!setProcessGroupLimit(uid_, pid_, limit_in_bytes_)) { PLOG(ERROR) << "setProcessGroupLimit failed"; } } } if ((flags_ & SVC_EXEC) != 0) { Loading init/service.h +7 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,9 @@ class Service { bool ParseOneshot(const std::vector<std::string>& args, std::string* err); bool ParseOnrestart(const std::vector<std::string>& args, std::string* err); bool ParseOomScoreAdjust(const std::vector<std::string>& args, std::string* err); bool ParseMemcgLimitInBytes(const std::vector<std::string>& args, std::string* err); bool ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args, std::string* err); bool ParseMemcgSwappiness(const std::vector<std::string>& args, std::string* err); bool ParseNamespace(const std::vector<std::string>& args, std::string* err); bool ParseSeclabel(const std::vector<std::string>& args, std::string* err); bool ParseSetenv(const std::vector<std::string>& args, std::string* err); Loading Loading @@ -181,6 +184,10 @@ class Service { int oom_score_adjust_; int swappiness_; int soft_limit_in_bytes_; int limit_in_bytes_; bool process_cgroup_empty_ = false; std::vector<std::string> args_; Loading libprocessgroup/include/processgroup/processgroup.h +4 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,10 @@ int killProcessGroupOnce(uid_t uid, int initialPid, int signal); int createProcessGroup(uid_t uid, int initialPid); bool setProcessGroupSwappiness(uid_t uid, int initialPid, int swappiness); bool setProcessGroupSoftLimit(uid_t uid, int initialPid, int64_t softLimitInBytes); bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes); void removeAllProcessGroups(void); __END_DECLS Loading libprocessgroup/processgroup.cpp +34 −13 Original line number Diff line number Diff line Loading @@ -35,12 +35,15 @@ #include <set> #include <thread> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/unique_fd.h> #include <private/android_filesystem_config.h> #include <processgroup/processgroup.h> using android::base::WriteStringToFile; using namespace std::chrono_literals; #define MEM_CGROUP_PATH "/dev/memcg/apps" Loading Loading @@ -402,22 +405,40 @@ int createProcessGroup(uid_t uid, int initialPid) strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path)); int fd = open(path, O_WRONLY); if (fd == -1) { int ret = -errno; PLOG(ERROR) << "Failed to open " << path; int ret = 0; if (!WriteStringToFile(std::to_string(initialPid), path)) { ret = -errno; PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << path; } return ret; } char pid[PROCESSGROUP_MAX_PID_LEN + 1] = {0}; int len = snprintf(pid, sizeof(pid), "%d", initialPid); static bool setProcessGroupValue(uid_t uid, int pid, const char* fileName, int64_t value) { char path[PROCESSGROUP_MAX_PATH_LEN] = {0}; if (strcmp(getCgroupRootPath(), MEM_CGROUP_PATH)) { PLOG(ERROR) << "Memcg is not mounted." << path; return false; } int ret = 0; if (write(fd, pid, len) < 0) { ret = -errno; PLOG(ERROR) << "Failed to write '" << pid << "' to " << path; convertUidPidToPath(path, sizeof(path), uid, pid); strlcat(path, fileName, sizeof(path)); if (!WriteStringToFile(std::to_string(value), path)) { PLOG(ERROR) << "Failed to write '" << value << "' to " << path; return false; } return true; } close(fd); return ret; bool setProcessGroupSwappiness(uid_t uid, int pid, int swappiness) { return setProcessGroupValue(uid, pid, "/memory.swappiness", swappiness); } bool setProcessGroupSoftLimit(uid_t uid, int pid, int64_t soft_limit_in_bytes) { return setProcessGroupValue(uid, pid, "/memory.soft_limit_in_bytes", soft_limit_in_bytes); } bool setProcessGroupLimit(uid_t uid, int pid, int64_t limit_in_bytes) { return setProcessGroupValue(uid, pid, "/memory.limit_in_bytes", limit_in_bytes); } Loading
init/README.md +12 −0 Original line number Diff line number Diff line Loading @@ -260,6 +260,18 @@ runs the service. > Sets the child's /proc/self/oom\_score\_adj to the specified value, which must range from -1000 to 1000. `memcg.swappiness <value>` > Sets the child's memory.swappiness to the specified value (only if memcg is mounted), which must be equal or greater than 0. `memcg.soft_limit_in_bytes <value>` > Sets the child's memory.soft_limit_in_bytes to the specified value (only if memcg is mounted), which must be equal or greater than 0. `memcg.limit_in_bytes <value>` > Sets the child's memory.limit_in_bytes to the specified value (only if memcg is mounted), which must be equal or greater than 0. `shutdown <shutdown_behavior>` > Set shutdown behavior of the service process. When this is not specified, the service is killed during shutdown process by using SIGTERM and SIGKILL. Loading
init/service.cpp +54 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,9 @@ Service::Service(const std::string& name, const std::vector<std::string>& args) ioprio_pri_(0), priority_(0), oom_score_adjust_(-1000), swappiness_(-1), soft_limit_in_bytes_(-1), limit_in_bytes_(-1), args_(args) { onrestart_.InitSingleTrigger("onrestart"); } Loading @@ -196,6 +199,9 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, ioprio_pri_(0), priority_(0), oom_score_adjust_(-1000), swappiness_(-1), soft_limit_in_bytes_(-1), limit_in_bytes_(-1), args_(args) { onrestart_.InitSingleTrigger("onrestart"); } Loading Loading @@ -491,6 +497,30 @@ bool Service::ParseOomScoreAdjust(const std::vector<std::string>& args, std::str return true; } bool Service::ParseMemcgSwappiness(const std::vector<std::string>& args, std::string* err) { if (!ParseInt(args[1], &swappiness_, 0)) { *err = "swappiness value must be equal or greater than 0"; return false; } return true; } bool Service::ParseMemcgLimitInBytes(const std::vector<std::string>& args, std::string* err) { if (!ParseInt(args[1], &limit_in_bytes_, 0)) { *err = "limit_in_bytes value must be equal or greater than 0"; return false; } return true; } bool Service::ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args, std::string* err) { if (!ParseInt(args[1], &soft_limit_in_bytes_, 0)) { *err = "soft_limit_in_bytes value must be equal or greater than 0"; return false; } return true; } bool Service::ParseSeclabel(const std::vector<std::string>& args, std::string* err) { seclabel_ = args[1]; return true; Loading Loading @@ -609,6 +639,12 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const { {"onrestart", {1, kMax, &Service::ParseOnrestart}}, {"oom_score_adjust", {1, 1, &Service::ParseOomScoreAdjust}}, {"memcg.swappiness", {1, 1, &Service::ParseMemcgSwappiness}}, {"memcg.soft_limit_in_bytes", {1, 1, &Service::ParseMemcgSoftLimitInBytes}}, {"memcg.limit_in_bytes", {1, 1, &Service::ParseMemcgLimitInBytes}}, {"namespace", {1, 2, &Service::ParseNamespace}}, {"seclabel", {1, 1, &Service::ParseSeclabel}}, {"setenv", {2, 2, &Service::ParseSetenv}}, Loading Loading @@ -795,6 +831,24 @@ bool Service::Start() { if (errno != 0) { PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '" << name_ << "'"; } else { if (swappiness_ != -1) { if (!setProcessGroupSwappiness(uid_, pid_, swappiness_)) { PLOG(ERROR) << "setProcessGroupSwappiness failed"; } } if (soft_limit_in_bytes_ != -1) { if (!setProcessGroupSoftLimit(uid_, pid_, soft_limit_in_bytes_)) { PLOG(ERROR) << "setProcessGroupSoftLimit failed"; } } if (limit_in_bytes_ != -1) { if (!setProcessGroupLimit(uid_, pid_, limit_in_bytes_)) { PLOG(ERROR) << "setProcessGroupLimit failed"; } } } if ((flags_ & SVC_EXEC) != 0) { Loading
init/service.h +7 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,9 @@ class Service { bool ParseOneshot(const std::vector<std::string>& args, std::string* err); bool ParseOnrestart(const std::vector<std::string>& args, std::string* err); bool ParseOomScoreAdjust(const std::vector<std::string>& args, std::string* err); bool ParseMemcgLimitInBytes(const std::vector<std::string>& args, std::string* err); bool ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args, std::string* err); bool ParseMemcgSwappiness(const std::vector<std::string>& args, std::string* err); bool ParseNamespace(const std::vector<std::string>& args, std::string* err); bool ParseSeclabel(const std::vector<std::string>& args, std::string* err); bool ParseSetenv(const std::vector<std::string>& args, std::string* err); Loading Loading @@ -181,6 +184,10 @@ class Service { int oom_score_adjust_; int swappiness_; int soft_limit_in_bytes_; int limit_in_bytes_; bool process_cgroup_empty_ = false; std::vector<std::string> args_; Loading
libprocessgroup/include/processgroup/processgroup.h +4 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,10 @@ int killProcessGroupOnce(uid_t uid, int initialPid, int signal); int createProcessGroup(uid_t uid, int initialPid); bool setProcessGroupSwappiness(uid_t uid, int initialPid, int swappiness); bool setProcessGroupSoftLimit(uid_t uid, int initialPid, int64_t softLimitInBytes); bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes); void removeAllProcessGroups(void); __END_DECLS Loading
libprocessgroup/processgroup.cpp +34 −13 Original line number Diff line number Diff line Loading @@ -35,12 +35,15 @@ #include <set> #include <thread> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/unique_fd.h> #include <private/android_filesystem_config.h> #include <processgroup/processgroup.h> using android::base::WriteStringToFile; using namespace std::chrono_literals; #define MEM_CGROUP_PATH "/dev/memcg/apps" Loading Loading @@ -402,22 +405,40 @@ int createProcessGroup(uid_t uid, int initialPid) strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path)); int fd = open(path, O_WRONLY); if (fd == -1) { int ret = -errno; PLOG(ERROR) << "Failed to open " << path; int ret = 0; if (!WriteStringToFile(std::to_string(initialPid), path)) { ret = -errno; PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << path; } return ret; } char pid[PROCESSGROUP_MAX_PID_LEN + 1] = {0}; int len = snprintf(pid, sizeof(pid), "%d", initialPid); static bool setProcessGroupValue(uid_t uid, int pid, const char* fileName, int64_t value) { char path[PROCESSGROUP_MAX_PATH_LEN] = {0}; if (strcmp(getCgroupRootPath(), MEM_CGROUP_PATH)) { PLOG(ERROR) << "Memcg is not mounted." << path; return false; } int ret = 0; if (write(fd, pid, len) < 0) { ret = -errno; PLOG(ERROR) << "Failed to write '" << pid << "' to " << path; convertUidPidToPath(path, sizeof(path), uid, pid); strlcat(path, fileName, sizeof(path)); if (!WriteStringToFile(std::to_string(value), path)) { PLOG(ERROR) << "Failed to write '" << value << "' to " << path; return false; } return true; } close(fd); return ret; bool setProcessGroupSwappiness(uid_t uid, int pid, int swappiness) { return setProcessGroupValue(uid, pid, "/memory.swappiness", swappiness); } bool setProcessGroupSoftLimit(uid_t uid, int pid, int64_t soft_limit_in_bytes) { return setProcessGroupValue(uid, pid, "/memory.soft_limit_in_bytes", soft_limit_in_bytes); } bool setProcessGroupLimit(uid_t uid, int pid, int64_t limit_in_bytes) { return setProcessGroupValue(uid, pid, "/memory.limit_in_bytes", limit_in_bytes); }