diff --git a/init/README.md b/init/README.md index 709c6675f..65d6543d8 100644 --- a/init/README.md +++ b/init/README.md @@ -192,11 +192,12 @@ runs the service. `oneshot` > Do not restart the service when it exits. -`class ` -> Specify a class name for the service. All services in a +`class [ \* ]` +> Specify class names for the service. All services in a named class may be started or stopped together. A service is in the class "default" if one is not specified via the - class option. + class option. Additional classnames beyond the (required) first + one are used to group services. `onrestart` > Execute a Command (see below) when service restarts. diff --git a/init/service.cpp b/init/service.cpp index c8d1cb166..c6ef83889 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -149,27 +149,44 @@ ServiceEnvironmentInfo::ServiceEnvironmentInfo(const std::string& name, : name(name), value(value) { } -Service::Service(const std::string& name, const std::string& classname, - const std::vector& args) - : name_(name), classname_(classname), flags_(0), pid_(0), - crash_count_(0), uid_(0), gid_(0), namespace_flags_(0), - seclabel_(""), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), - priority_(0), oom_score_adjust_(-1000), args_(args) { +Service::Service(const std::string& name, const std::vector& args) + : name_(name), + classnames_({"default"}), + flags_(0), + pid_(0), + crash_count_(0), + uid_(0), + gid_(0), + namespace_flags_(0), + seclabel_(""), + ioprio_class_(IoSchedClass_NONE), + ioprio_pri_(0), + priority_(0), + oom_score_adjust_(-1000), + args_(args) { onrestart_.InitSingleTrigger("onrestart"); } -Service::Service(const std::string& name, const std::string& classname, - unsigned flags, uid_t uid, gid_t gid, - const std::vector& supp_gids, - const CapSet& capabilities, unsigned namespace_flags, - const std::string& seclabel, +Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, + const std::vector& supp_gids, const CapSet& capabilities, + unsigned namespace_flags, const std::string& seclabel, const std::vector& args) - : name_(name), classname_(classname), flags_(flags), pid_(0), - crash_count_(0), uid_(uid), gid_(gid), - supp_gids_(supp_gids), capabilities_(capabilities), - namespace_flags_(namespace_flags), seclabel_(seclabel), - ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0), - oom_score_adjust_(-1000), args_(args) { + : name_(name), + classnames_({"default"}), + flags_(flags), + pid_(0), + crash_count_(0), + uid_(uid), + gid_(gid), + supp_gids_(supp_gids), + capabilities_(capabilities), + namespace_flags_(namespace_flags), + seclabel_(seclabel), + ioprio_class_(IoSchedClass_NONE), + ioprio_pri_(0), + priority_(0), + oom_score_adjust_(-1000), + args_(args) { onrestart_.InitSingleTrigger("onrestart"); } @@ -297,7 +314,7 @@ bool Service::Reap() { void Service::DumpState() const { LOG(INFO) << "service " << name_; - LOG(INFO) << " class '" << classname_ << "'"; + LOG(INFO) << " class '" << android::base::Join(classnames_, " ") << "'"; LOG(INFO) << " exec "<< android::base::Join(args_, " "); std::for_each(descriptors_.begin(), descriptors_.end(), [] (const auto& info) { LOG(INFO) << *info; }); @@ -334,7 +351,7 @@ bool Service::ParseCapabilities(const std::vector& args, std::strin } bool Service::ParseClass(const std::vector& args, std::string* err) { - classname_ = args[1]; + classnames_ = std::set(args.begin() + 1, args.end()); return true; } @@ -516,10 +533,11 @@ private: Service::OptionParserMap::Map& Service::OptionParserMap::map() const { constexpr std::size_t kMax = std::numeric_limits::max(); + // clang-format off static const Map option_parsers = { {"capabilities", {1, kMax, &Service::ParseCapabilities}}, - {"class", {1, 1, &Service::ParseClass}}, + {"class", {1, kMax, &Service::ParseClass}}, {"console", {0, 1, &Service::ParseConsole}}, {"critical", {0, 0, &Service::ParseCritical}}, {"disabled", {0, 0, &Service::ParseDisabled}}, @@ -539,6 +557,7 @@ Service::OptionParserMap::Map& Service::OptionParserMap::map() const { {"user", {1, 1, &Service::ParseUser}}, {"writepid", {1, kMax, &Service::ParseWritepid}}, }; + // clang-format on return option_parsers; } @@ -889,8 +908,8 @@ Service* ServiceManager::MakeExecOneshotService(const std::vector& } } - auto svc_p = std::make_unique(name, "default", flags, uid, gid, supp_gids, - no_capabilities, namespace_flags, seclabel, str_args); + auto svc_p = std::make_unique(name, flags, uid, gid, supp_gids, no_capabilities, + namespace_flags, seclabel, str_args); Service* svc = svc_p.get(); services_.emplace_back(std::move(svc_p)); @@ -940,7 +959,7 @@ void ServiceManager::ForEachService(const std::function& callbac void ServiceManager::ForEachServiceInClass(const std::string& classname, void (*func)(Service* svc)) const { for (const auto& s : services_) { - if (classname == s->classname()) { + if (s->classnames().find(classname) != s->classnames().end()) { func(s.get()); } } @@ -1034,7 +1053,7 @@ bool ServiceParser::ParseSection(const std::vector& args, } std::vector str_args(args.begin() + 2, args.end()); - service_ = std::make_unique(name, "default", str_args); + service_ = std::make_unique(name, str_args); return true; } diff --git a/init/service.h b/init/service.h index 08388e239..9a9046b9e 100644 --- a/init/service.h +++ b/init/service.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -61,12 +62,10 @@ struct ServiceEnvironmentInfo { }; class Service { -public: - Service(const std::string& name, const std::string& classname, - const std::vector& args); + public: + Service(const std::string& name, const std::vector& args); - Service(const std::string& name, const std::string& classname, - unsigned flags, uid_t uid, gid_t gid, + Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, const std::vector& supp_gids, const CapSet& capabilities, unsigned namespace_flags, const std::string& seclabel, const std::vector& args); @@ -84,10 +83,10 @@ public: bool Reap(); void DumpState() const; void SetShutdownCritical() { flags_ |= SVC_SHUTDOWN_CRITICAL; } - bool IsShutdownCritical() { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; } + bool IsShutdownCritical() const { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; } const std::string& name() const { return name_; } - const std::string& classname() const { return classname_; } + const std::set& classnames() const { return classnames_; } unsigned flags() const { return flags_; } pid_t pid() const { return pid_; } uid_t uid() const { return uid_; } @@ -100,7 +99,7 @@ public: void set_keychord_id(int keychord_id) { keychord_id_ = keychord_id; } const std::vector& args() const { return args_; } -private: + private: using OptionParser = bool (Service::*) (const std::vector& args, std::string* err); class OptionParserMap; @@ -136,7 +135,7 @@ private: bool AddDescriptor(const std::vector& args, std::string* err); std::string name_; - std::string classname_; + std::set classnames_; std::string console_; unsigned flags_;