init: move exec operations out of ServiceManager
These can be implemented without ServiceManager, so we remove them and
make ServiceManager slightly less of a God class.
Test: boot bullhead
Test: init unit tests
Change-Id: Ia6e546fe5292255412245256f7d230af4ece135f
diff --git a/init/service.cpp b/init/service.cpp
index d72433a..7f79584 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -156,6 +156,7 @@
}
unsigned long Service::next_start_order_ = 1;
+bool Service::is_exec_service_running_ = false;
Service::Service(const std::string& name, const std::vector<std::string>& args)
: Service(name, 0, 0, 0, {}, 0, 0, "", args) {}
@@ -280,9 +281,9 @@
std::for_each(descriptors_.begin(), descriptors_.end(),
std::bind(&DescriptorInfo::Clean, std::placeholders::_1));
- if (flags_ & SVC_TEMPORARY) {
- return;
- }
+ if (flags_ & SVC_EXEC) UnSetExec();
+
+ if (flags_ & SVC_TEMPORARY) return;
pid_ = 0;
flags_ &= (~SVC_RUNNING);
@@ -653,15 +654,20 @@
return (this->*parser)(args, err);
}
-bool Service::ExecStart(std::unique_ptr<android::base::Timer>* exec_waiter) {
- flags_ |= SVC_EXEC | SVC_ONESHOT;
-
- exec_waiter->reset(new android::base::Timer);
+bool Service::ExecStart() {
+ flags_ |= SVC_ONESHOT;
if (!Start()) {
- exec_waiter->reset();
return false;
}
+
+ flags_ |= SVC_EXEC;
+ is_exec_service_running_ = true;
+
+ LOG(INFO) << "SVC_EXEC pid " << pid_ << " (uid " << uid_ << " gid " << gid_ << "+"
+ << supp_gids_.size() << " context " << (!seclabel_.empty() ? seclabel_ : "default")
+ << ") started; waiting...";
+
return true;
}
@@ -836,12 +842,6 @@
}
}
- if ((flags_ & SVC_EXEC) != 0) {
- LOG(INFO) << "SVC_EXEC pid " << pid_ << " (uid " << uid_ << " gid " << gid_ << "+"
- << supp_gids_.size() << " context "
- << (!seclabel_.empty() ? seclabel_ : "default") << ") started; waiting...";
- }
-
NotifyStateChange("running");
return true;
}
@@ -935,8 +935,6 @@
close(fd);
}
-int ServiceManager::exec_count_ = 0;
-
ServiceManager::ServiceManager() {
}
@@ -949,36 +947,7 @@
services_.emplace_back(std::move(service));
}
-bool ServiceManager::Exec(const std::vector<std::string>& args) {
- Service* svc = MakeExecOneshotService(args);
- if (!svc) {
- LOG(ERROR) << "Could not create exec service";
- return false;
- }
- if (!svc->ExecStart(&exec_waiter_)) {
- LOG(ERROR) << "Could not start exec service";
- ServiceManager::GetInstance().RemoveService(*svc);
- return false;
- }
- return true;
-}
-
-bool ServiceManager::ExecStart(const std::string& name) {
- Service* svc = FindServiceByName(name);
- if (!svc) {
- LOG(ERROR) << "ExecStart(" << name << "): Service not found";
- return false;
- }
- if (!svc->ExecStart(&exec_waiter_)) {
- LOG(ERROR) << "ExecStart(" << name << "): Could not start Service";
- return false;
- }
- return true;
-}
-
-bool ServiceManager::IsWaitingForExec() const { return exec_waiter_ != nullptr; }
-
-Service* ServiceManager::MakeExecOneshotService(const std::vector<std::string>& args) {
+std::unique_ptr<Service> Service::MakeTemporaryOneshotService(const std::vector<std::string>& args) {
// Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS...
// SECLABEL can be a - to denote default
std::size_t command_arg = 1;
@@ -999,10 +968,11 @@
}
std::vector<std::string> str_args(args.begin() + command_arg, args.end());
- exec_count_++;
- std::string name = "exec " + std::to_string(exec_count_) + " (" + Join(str_args, " ") + ")";
+ static size_t exec_count = 0;
+ exec_count++;
+ std::string name = "exec " + std::to_string(exec_count) + " (" + Join(str_args, " ") + ")";
- unsigned flags = SVC_EXEC | SVC_ONESHOT | SVC_TEMPORARY;
+ unsigned flags = SVC_ONESHOT | SVC_TEMPORARY;
CapSet no_capabilities;
unsigned namespace_flags = 0;
@@ -1037,12 +1007,8 @@
}
}
- auto svc_p = std::make_unique<Service>(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));
-
- return svc;
+ return std::make_unique<Service>(name, flags, uid, gid, supp_gids, no_capabilities,
+ namespace_flags, seclabel, str_args);
}
Service* ServiceManager::FindServiceByName(const std::string& name) const {
@@ -1154,8 +1120,10 @@
if (svc) {
name = StringPrintf("Service '%s' (pid %d)", svc->name().c_str(), pid);
if (svc->flags() & SVC_EXEC) {
- wait_string = StringPrintf(" waiting took %f seconds",
- exec_waiter_->duration().count() / 1000.0f);
+ auto exec_duration = boot_clock::now() - svc->time_started();
+ auto exec_duration_ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count();
+ wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f);
}
} else {
name = StringPrintf("Untracked pid %d", pid);
@@ -1174,9 +1142,6 @@
svc->Reap();
- if (svc->flags() & SVC_EXEC) {
- exec_waiter_.reset();
- }
if (svc->flags() & SVC_TEMPORARY) {
RemoveService(*svc);
}
@@ -1189,15 +1154,6 @@
}
}
-void ServiceManager::ClearExecWait() {
- // Clear EXEC flag if there is one pending
- // And clear the wait flag
- for (const auto& s : services_) {
- s->UnSetExec();
- }
- exec_waiter_.reset();
-}
-
bool ServiceParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,
int line, std::string* err) {
if (args.size() < 3) {