init: rename ServiceManager to ServiceList and clean it up

ServiceManager is essentially just a list now that the rest of its
functionality has been moved elsewhere, so the class is renamed
appropriately.

The ServiceList::Find* functions have been cleaned up into a single
smaller interface.
The ServiceList::ForEach functions have been removed in favor of
ServiceList itself being directly iterable.

Test: boot bullhead
Change-Id: Ibd57c103338f03b83d81e8b48ea0e46cd48fd8f0
This commit is contained in:
Tom Cherry 2017-07-27 16:20:58 -07:00
parent eeee83106b
commit 911b9b1d6e
8 changed files with 91 additions and 127 deletions

View File

@ -124,31 +124,32 @@ static int reboot_into_recovery(const std::vector<std::string>& options) {
return 0;
}
template <typename F>
static void ForEachServiceInClass(const std::string& classname, F function) {
for (const auto& service : ServiceList::GetInstance()) {
if (service->classnames().count(classname)) std::invoke(function, service);
}
}
static int do_class_start(const std::vector<std::string>& args) {
/* Starting a class does not start services
* which are explicitly disabled. They must
* be started individually.
*/
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
// Starting a class does not start services which are explicitly disabled.
// They must be started individually.
ForEachServiceInClass(args[1], &Service::StartIfNotDisabled);
return 0;
}
static int do_class_stop(const std::vector<std::string>& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->Stop(); });
ForEachServiceInClass(args[1], &Service::Stop);
return 0;
}
static int do_class_reset(const std::vector<std::string>& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->Reset(); });
ForEachServiceInClass(args[1], &Service::Reset);
return 0;
}
static int do_class_restart(const std::vector<std::string>& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->Restart(); });
ForEachServiceInClass(args[1], &Service::Restart);
return 0;
}
@ -162,7 +163,7 @@ static int do_domainname(const std::vector<std::string>& args) {
}
static int do_enable(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
Service* svc = ServiceList::GetInstance().FindService(args[1]);
if (!svc) {
return -1;
}
@ -179,12 +180,12 @@ static int do_exec(const std::vector<std::string>& args) {
LOG(ERROR) << "Failed to Start exec service";
return -1;
}
ServiceManager::GetInstance().AddService(std::move(service));
ServiceList::GetInstance().AddService(std::move(service));
return 0;
}
static int do_exec_start(const std::vector<std::string>& args) {
Service* service = ServiceManager::GetInstance().FindServiceByName(args[1]);
Service* service = ServiceList::GetInstance().FindService(args[1]);
if (!service) {
LOG(ERROR) << "ExecStart(" << args[1] << "): Service not found";
return -1;
@ -408,8 +409,8 @@ exit_success:
*/
static void import_late(const std::vector<std::string>& args, size_t start_index, size_t end_index) {
auto& action_manager = ActionManager::GetInstance();
auto& service_manager = ServiceManager::GetInstance();
Parser parser = CreateParser(action_manager, service_manager);
auto& service_list = ServiceList::GetInstance();
Parser parser = CreateParser(action_manager, service_list);
if (end_index <= start_index) {
// Fallbacks for partitions on which early mount isn't enabled.
for (const auto& path : late_import_paths) {
@ -599,7 +600,7 @@ static int do_setrlimit(const std::vector<std::string>& args) {
}
static int do_start(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
Service* svc = ServiceList::GetInstance().FindService(args[1]);
if (!svc) {
LOG(ERROR) << "do_start: Service " << args[1] << " not found";
return -1;
@ -610,7 +611,7 @@ static int do_start(const std::vector<std::string>& args) {
}
static int do_stop(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
Service* svc = ServiceList::GetInstance().FindService(args[1]);
if (!svc) {
LOG(ERROR) << "do_stop: Service " << args[1] << " not found";
return -1;
@ -620,7 +621,7 @@ static int do_stop(const std::vector<std::string>& args) {
}
static int do_restart(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
Service* svc = ServiceList::GetInstance().FindService(args[1]);
if (!svc) {
LOG(ERROR) << "do_restart: Service " << args[1] << " not found";
return -1;

View File

@ -98,22 +98,22 @@ static bool shutting_down;
std::vector<std::string> late_import_paths;
void DumpState() {
ServiceManager::GetInstance().DumpState();
ServiceList::GetInstance().DumpState();
ActionManager::GetInstance().DumpState();
}
Parser CreateParser(ActionManager& action_manager, ServiceManager& service_manager) {
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
Parser parser;
parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_manager));
parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list));
parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager));
parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
return parser;
}
static void LoadBootScripts(ActionManager& action_manager, ServiceManager& service_manager) {
Parser parser = CreateParser(action_manager, service_manager);
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
Parser parser = CreateParser(action_manager, service_list);
std::string bootscript = GetProperty("ro.boot.init_rc", "");
if (bootscript.empty()) {
@ -221,8 +221,8 @@ void property_changed(const std::string& name, const std::string& value) {
static std::optional<boot_clock::time_point> RestartProcesses() {
std::optional<boot_clock::time_point> next_process_restart_time;
ServiceManager::GetInstance().ForEachService([&next_process_restart_time](Service* s) {
if (!(s->flags() & SVC_RESTARTING)) return;
for (const auto& s : ServiceList::GetInstance()) {
if (!(s->flags() & SVC_RESTARTING)) continue;
auto restart_time = s->time_started() + 5s;
if (boot_clock::now() > restart_time) {
@ -232,12 +232,12 @@ static std::optional<boot_clock::time_point> RestartProcesses() {
next_process_restart_time = restart_time;
}
}
});
}
return next_process_restart_time;
}
void handle_control_message(const std::string& msg, const std::string& name) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(name);
Service* svc = ServiceList::GetInstance().FindService(name);
if (svc == nullptr) {
LOG(ERROR) << "no such service '" << name << "'";
return;
@ -1139,7 +1139,7 @@ int main(int argc, char** argv) {
Action::set_function_map(&function_map);
ActionManager& am = ActionManager::GetInstance();
ServiceManager& sm = ServiceManager::GetInstance();
ServiceList& sm = ServiceList::GetInstance();
LoadBootScripts(am, sm);

View File

@ -38,7 +38,7 @@ extern struct selabel_handle *sehandle_prop;
extern std::vector<std::string> late_import_paths;
Parser CreateParser(ActionManager& action_manager, ServiceManager& service_manager);
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
void handle_control_message(const std::string& msg, const std::string& arg);

View File

@ -79,7 +79,7 @@ static void handle_keychord() {
// Only handle keychords if adb is enabled.
std::string adb_enabled = android::base::GetProperty("init.svc.adbd", "");
if (adb_enabled == "running") {
Service* svc = ServiceManager::GetInstance().FindServiceByKeychord(id);
Service* svc = ServiceList::GetInstance().FindService(id, &Service::keychord_id);
if (svc) {
LOG(INFO) << "Starting service " << svc->name() << " from keychord " << id;
svc->Start();
@ -92,7 +92,9 @@ static void handle_keychord() {
}
void keychord_init() {
ServiceManager::GetInstance().ForEachService(add_service_keycodes);
for (const auto& service : ServiceList::GetInstance()) {
add_service_keycodes(service.get());
}
// Nothing to do if no services require keychords.
if (!keychords) {

View File

@ -374,7 +374,7 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
// watchdogd is a vendor specific component but should be alive to complete shutdown safely.
const std::set<std::string> to_starts{"watchdogd"};
ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) {
for (const auto& s : ServiceList::GetInstance()) {
if (kill_after_apps.count(s->name())) {
s->SetShutdownCritical();
} else if (to_starts.count(s->name())) {
@ -383,14 +383,15 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
} else if (s->IsShutdownCritical()) {
s->Start(); // start shutdown critical service if not started
}
});
}
Service* bootAnim = ServiceManager::GetInstance().FindServiceByName("bootanim");
Service* surfaceFlinger = ServiceManager::GetInstance().FindServiceByName("surfaceflinger");
Service* bootAnim = ServiceList::GetInstance().FindService("bootanim");
Service* surfaceFlinger = ServiceList::GetInstance().FindService("surfaceflinger");
if (bootAnim != nullptr && surfaceFlinger != nullptr && surfaceFlinger->IsRunning()) {
ServiceManager::GetInstance().ForEachServiceInClass("animation", [](Service* s) {
s->SetShutdownCritical(); // will not check animation class separately
});
// will not check animation class separately
for (const auto& service : ServiceList::GetInstance()) {
if (service->classnames().count("animation")) service->SetShutdownCritical();
}
}
// optional shutdown step
@ -399,9 +400,9 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
LOG(INFO) << "terminating init services";
// Ask all services to terminate except shutdown critical ones.
ServiceManager::GetInstance().ForEachServiceShutdownOrder([](Service* s) {
for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
if (!s->IsShutdownCritical()) s->Terminate();
});
}
int service_count = 0;
// Only wait up to half of timeout here
@ -410,7 +411,7 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
ReapAnyOutstandingChildren();
service_count = 0;
ServiceManager::GetInstance().ForEachService([&service_count](Service* s) {
for (const auto& s : ServiceList::GetInstance()) {
// Count the number of services running except shutdown critical.
// Exclude the console as it will ignore the SIGTERM signal
// and not exit.
@ -419,7 +420,7 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
if (!s->IsShutdownCritical() && s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
service_count++;
}
});
}
if (service_count == 0) {
// All terminable services terminated. We can exit early.
@ -435,13 +436,13 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
// minimum safety steps before restarting
// 2. kill all services except ones that are necessary for the shutdown sequence.
ServiceManager::GetInstance().ForEachServiceShutdownOrder([](Service* s) {
for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
if (!s->IsShutdownCritical()) s->Stop();
});
}
ReapAnyOutstandingChildren();
// 3. send volume shutdown to vold
Service* voldService = ServiceManager::GetInstance().FindServiceByName("vold");
Service* voldService = ServiceList::GetInstance().FindService("vold");
if (voldService != nullptr && voldService->IsRunning()) {
ShutdownVold();
voldService->Stop();
@ -449,9 +450,9 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
LOG(INFO) << "vold not running, skipping vold shutdown";
}
// logcat stopped here
ServiceManager::GetInstance().ForEachServiceShutdownOrder([&kill_after_apps](Service* s) {
for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
if (kill_after_apps.count(s->name())) s->Stop();
});
}
// 4. sync, try umount, and optionally run fsck for user shutdown
sync();
UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
@ -526,7 +527,9 @@ bool HandlePowerctlMessage(const std::string& command) {
ResetWaitForProp();
// Clear EXEC flag if there is one pending
ServiceManager::GetInstance().ForEachService([](Service* s) { s->UnSetExec(); });
for (const auto& s : ServiceList::GetInstance()) {
s->UnSetExec();
}
return true;
}

View File

@ -935,15 +935,14 @@ void Service::OpenConsole() const {
close(fd);
}
ServiceManager::ServiceManager() {
}
ServiceList::ServiceList() {}
ServiceManager& ServiceManager::GetInstance() {
static ServiceManager instance;
ServiceList& ServiceList::GetInstance() {
static ServiceList instance;
return instance;
}
void ServiceManager::AddService(std::unique_ptr<Service> service) {
void ServiceList::AddService(std::unique_ptr<Service> service) {
services_.emplace_back(std::move(service));
}
@ -1011,69 +1010,18 @@ std::unique_ptr<Service> Service::MakeTemporaryOneshotService(const std::vector<
namespace_flags, seclabel, str_args);
}
Service* ServiceManager::FindServiceByName(const std::string& name) const {
auto svc = std::find_if(services_.begin(), services_.end(),
[&name] (const std::unique_ptr<Service>& s) {
return name == s->name();
});
if (svc != services_.end()) {
return svc->get();
}
return nullptr;
}
Service* ServiceManager::FindServiceByPid(pid_t pid) const {
auto svc = std::find_if(services_.begin(), services_.end(),
[&pid] (const std::unique_ptr<Service>& s) {
return s->pid() == pid;
});
if (svc != services_.end()) {
return svc->get();
}
return nullptr;
}
Service* ServiceManager::FindServiceByKeychord(int keychord_id) const {
auto svc = std::find_if(services_.begin(), services_.end(),
[&keychord_id] (const std::unique_ptr<Service>& s) {
return s->keychord_id() == keychord_id;
});
if (svc != services_.end()) {
return svc->get();
}
return nullptr;
}
void ServiceManager::ForEachService(const std::function<void(Service*)>& callback) const {
for (const auto& s : services_) {
callback(s.get());
}
}
// Shutdown services in the opposite order that they were started.
void ServiceManager::ForEachServiceShutdownOrder(const std::function<void(Service*)>& callback) const {
const std::vector<Service*> ServiceList::services_in_shutdown_order() const {
std::vector<Service*> shutdown_services;
for (const auto& service : services_) {
if (service->start_order() > 0) shutdown_services.emplace_back(service.get());
}
std::sort(shutdown_services.begin(), shutdown_services.end(),
[](const auto& a, const auto& b) { return a->start_order() > b->start_order(); });
for (const auto& service : shutdown_services) {
callback(service);
}
return shutdown_services;
}
void ServiceManager::ForEachServiceInClass(const std::string& classname,
void (*func)(Service* svc)) const {
for (const auto& s : services_) {
if (s->classnames().find(classname) != s->classnames().end()) {
func(s.get());
}
}
}
void ServiceManager::RemoveService(const Service& svc) {
void ServiceList::RemoveService(const Service& svc) {
auto svc_it = std::find_if(services_.begin(), services_.end(),
[&svc] (const std::unique_ptr<Service>& s) {
return svc.name() == s->name();
@ -1085,7 +1033,7 @@ void ServiceManager::RemoveService(const Service& svc) {
services_.erase(svc_it);
}
void ServiceManager::DumpState() const {
void ServiceList::DumpState() const {
for (const auto& s : services_) {
s->DumpState();
}
@ -1104,7 +1052,7 @@ bool ServiceParser::ParseSection(std::vector<std::string>&& args, const std::str
return false;
}
Service* old_service = service_manager_->FindServiceByName(name);
Service* old_service = service_list_->FindService(name);
if (old_service) {
*err = "ignored duplicate definition of service '" + name + "'";
return false;
@ -1121,7 +1069,7 @@ bool ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line,
void ServiceParser::EndSection() {
if (service_) {
service_manager_->AddService(std::move(service_));
service_list_->AddService(std::move(service_));
}
}

View File

@ -206,32 +206,42 @@ class Service {
std::vector<std::string> args_;
};
class ServiceManager {
class ServiceList {
public:
static ServiceManager& GetInstance();
static ServiceList& GetInstance();
// Exposed for testing
ServiceManager();
ServiceList();
void AddService(std::unique_ptr<Service> service);
Service* FindServiceByName(const std::string& name) const;
Service* FindServiceByPid(pid_t pid) const;
Service* FindServiceByKeychord(int keychord_id) const;
void ForEachService(const std::function<void(Service*)>& callback) const;
void ForEachServiceShutdownOrder(const std::function<void(Service*)>& callback) const;
void ForEachServiceInClass(const std::string& classname,
void (*func)(Service* svc)) const;
void RemoveService(const Service& svc);
template <typename T, typename F = decltype(&Service::name)>
Service* FindService(T value, F function = &Service::name) const {
auto svc = std::find_if(services_.begin(), services_.end(),
[&function, &value](const std::unique_ptr<Service>& s) {
return std::invoke(function, s) == value;
});
if (svc != services_.end()) {
return svc->get();
}
return nullptr;
}
void DumpState() const;
auto begin() const { return services_.begin(); }
auto end() const { return services_.end(); }
const std::vector<std::unique_ptr<Service>>& services() const { return services_; }
const std::vector<Service*> services_in_shutdown_order() const;
private:
std::vector<std::unique_ptr<Service>> services_;
};
class ServiceParser : public SectionParser {
public:
ServiceParser(ServiceManager* service_manager)
: service_manager_(service_manager), service_(nullptr) {}
ServiceParser(ServiceList* service_list) : service_list_(service_list), service_(nullptr) {}
bool ParseSection(std::vector<std::string>&& args, const std::string& filename, int line,
std::string* err) override;
bool ParseLineSection(std::vector<std::string>&& args, int line, std::string* err) override;
@ -240,7 +250,7 @@ class ServiceParser : public SectionParser {
private:
bool IsValidName(const std::string& name) const;
ServiceManager* service_manager_;
ServiceList* service_list_;
std::unique_ptr<Service> service_;
};

View File

@ -62,7 +62,7 @@ static bool ReapOneProcess() {
if (PropertyChildReap(pid)) return true;
Service* service = ServiceManager::GetInstance().FindServiceByPid(pid);
Service* service = ServiceList::GetInstance().FindService(pid, &Service::pid);
std::string name;
std::string wait_string;
@ -90,7 +90,7 @@ static bool ReapOneProcess() {
service->Reap();
if (service->flags() & SVC_TEMPORARY) {
ServiceManager::GetInstance().RemoveService(*service);
ServiceList::GetInstance().RemoveService(*service);
}
return true;