Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b81f2d6 authored by Tom Cherry's avatar Tom Cherry
Browse files

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
parent d269e3a7
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -170,11 +170,30 @@ static int do_enable(const std::vector<std::string>& args) {
}

static int do_exec(const std::vector<std::string>& args) {
    return ServiceManager::GetInstance().Exec(args) ? 0 : -1;
    auto service = Service::MakeTemporaryOneshotService(args);
    if (!service) {
        LOG(ERROR) << "Failed to create exec service: " << android::base::Join(args, " ");
        return -1;
    }
    if (!service->ExecStart()) {
        LOG(ERROR) << "Failed to Start exec service";
        return -1;
    }
    ServiceManager::GetInstance().AddService(std::move(service));
    return 0;
}

static int do_exec_start(const std::vector<std::string>& args) {
    return ServiceManager::GetInstance().ExecStart(args[1]) ? 0 : -1;
    Service* service = ServiceManager::GetInstance().FindServiceByName(args[1]);
    if (!service) {
        LOG(ERROR) << "ExecStart(" << args[1] << "): Service not found";
        return -1;
    }
    if (!service->ExecStart()) {
        LOG(ERROR) << "ExecStart(" << args[1] << "): Could not start Service";
        return -1;
    }
    return 0;
}

static int do_export(const std::vector<std::string>& args) {
+2 −2
Original line number Diff line number Diff line
@@ -1180,10 +1180,10 @@ int main(int argc, char** argv) {
        // By default, sleep until something happens.
        int epoll_timeout_ms = -1;

        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
        if (!(waiting_for_prop || Service::is_exec_service_running())) {
            am.ExecuteOneCommand();
        }
        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
        if (!(waiting_for_prop || Service::is_exec_service_running())) {
            if (!shutting_down) {
                auto next_process_restart_time = RestartProcesses();

+2 −4
Original line number Diff line number Diff line
@@ -524,10 +524,8 @@ bool HandlePowerctlMessage(const std::string& command) {
    // Skip wait for prop if it is in progress
    ResetWaitForProp();

    // Skip wait for exec if it is in progress
    if (ServiceManager::GetInstance().IsWaitingForExec()) {
        ServiceManager::GetInstance().ClearExecWait();
    }
    // Clear EXEC flag if there is one pending
    ServiceManager::GetInstance().ForEachService([](Service* s) { s->UnSetExec(); });

    return true;
}
+25 −69
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ ServiceEnvironmentInfo::ServiceEnvironmentInfo(const std::string& name,
}

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 @@ void Service::Reap() {
    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 @@ bool Service::ParseLine(const std::vector<std::string>& args, std::string* err)
    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 @@ bool Service::Start() {
        }
    }

    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 @@ void Service::OpenConsole() const {
    close(fd);
}

int ServiceManager::exec_count_ = 0;

ServiceManager::ServiceManager() {
}

@@ -949,36 +947,7 @@ void ServiceManager::AddService(std::unique_ptr<Service> service) {
    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 @@ Service* ServiceManager::MakeExecOneshotService(const std::vector<std::string>&
    }
    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 @@ Service* ServiceManager::MakeExecOneshotService(const std::vector<std::string>&
        }
    }

    auto svc_p = std::make_unique<Service>(name, flags, uid, gid, supp_gids, no_capabilities,
    return 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;
}

Service* ServiceManager::FindServiceByName(const std::string& name) const {
@@ -1154,8 +1120,10 @@ bool ServiceManager::ReapOneProcess() {
    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 @@ bool ServiceManager::ReapOneProcess() {

    svc->Reap();

    if (svc->flags() & SVC_EXEC) {
        exec_waiter_.reset();
    }
    if (svc->flags() & SVC_TEMPORARY) {
        RemoveService(*svc);
    }
@@ -1189,15 +1154,6 @@ void ServiceManager::ReapAnyOutstandingChildren() {
    }
}

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) {
+10 −10
Original line number Diff line number Diff line
@@ -73,9 +73,11 @@ class Service {
            unsigned namespace_flags, const std::string& seclabel,
            const std::vector<std::string>& args);

    static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);

    bool IsRunning() { return (flags_ & SVC_RUNNING) != 0; }
    bool ParseLine(const std::vector<std::string>& args, std::string* err);
    bool ExecStart(std::unique_ptr<android::base::Timer>* exec_waiter);
    bool ExecStart();
    bool Start();
    bool StartIfNotDisabled();
    bool Enable();
@@ -87,7 +89,12 @@ class Service {
    void DumpState() const;
    void SetShutdownCritical() { flags_ |= SVC_SHUTDOWN_CRITICAL; }
    bool IsShutdownCritical() const { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; }
    void UnSetExec() { flags_ &= ~SVC_EXEC; }
    void UnSetExec() {
        is_exec_service_running_ = false;
        flags_ &= ~SVC_EXEC;
    }

    static bool is_exec_service_running() { return is_exec_service_running_; }

    const std::string& name() const { return name_; }
    const std::set<std::string>& classnames() const { return classnames_; }
@@ -151,6 +158,7 @@ class Service {
    bool AddDescriptor(const std::vector<std::string>& args, std::string* err);

    static unsigned long next_start_order_;
    static bool is_exec_service_running_;

    std::string name_;
    std::set<std::string> classnames_;
@@ -206,10 +214,6 @@ class ServiceManager {
    ServiceManager();

    void AddService(std::unique_ptr<Service> service);
    Service* MakeExecOneshotService(const std::vector<std::string>& args);
    bool Exec(const std::vector<std::string>& args);
    bool ExecStart(const std::string& name);
    bool IsWaitingForExec() const;
    Service* FindServiceByName(const std::string& name) const;
    Service* FindServiceByPid(pid_t pid) const;
    Service* FindServiceByKeychord(int keychord_id) const;
@@ -220,16 +224,12 @@ class ServiceManager {
    void ReapAnyOutstandingChildren();
    void RemoveService(const Service& svc);
    void DumpState() const;
    void ClearExecWait();

  private:
    // Cleans up a child process that exited.
    // Returns true iff a children was cleaned up.
    bool ReapOneProcess();

    static int exec_count_; // Every service needs a unique name.
    std::unique_ptr<android::base::Timer> exec_waiter_;

    std::vector<std::unique_ptr<Service>> services_;
};

Loading