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

Commit 8772b368 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic 'exec-start-update-verifier'

* changes:
  init.rc: launch update_verifier with exec_start
  init: add exec_start command
parents 7bcce1e3 1e2d8c7f
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -311,6 +311,12 @@ Commands
  groups can be provided. No other commands will be run until this one
  finishes. _seclabel_ can be a - to denote default. Properties are expanded
  within _argument_.
  Init halts executing commands until the forked process exits.

`exec_start <service>`
> Start service a given service and halt processing of additional init commands
  until it returns.  It functions similarly to the `exec` command, but uses an
  existing service definition instead of providing them as arguments.

`export <name> <value>`
> Set the environment variable _name_ equal to _value_ in the
+8 −13
Original line number Diff line number Diff line
@@ -167,19 +167,11 @@ static int do_enable(const std::vector<std::string>& args) {
}

static int do_exec(const std::vector<std::string>& args) {
    Service* svc = ServiceManager::GetInstance().MakeExecOneshotService(args);
    if (!svc) {
        return -1;
    }
    if (!start_waiting_for_exec()) {
        return -1;
    return ServiceManager::GetInstance().Exec(args) ? 0 : -1;
}
    if (!svc->Start()) {
        stop_waiting_for_exec();
        ServiceManager::GetInstance().RemoveService(*svc);
        return -1;
    }
    return 0;

static int do_exec_start(const std::vector<std::string>& args) {
    return ServiceManager::GetInstance().ExecStart(args[1]) ? 0 : -1;
}

static int do_export(const std::vector<std::string>& args) {
@@ -897,6 +889,7 @@ static int do_init_user0(const std::vector<std::string>& args) {

BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    // clang-format off
    static const Map builtin_functions = {
        {"bootchart",               {1,     1,    do_bootchart}},
        {"chmod",                   {2,     2,    do_chmod}},
@@ -909,6 +902,7 @@ BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
        {"domainname",              {1,     1,    do_domainname}},
        {"enable",                  {1,     1,    do_enable}},
        {"exec",                    {1,     kMax, do_exec}},
        {"exec_start",              {1,     1,    do_exec_start}},
        {"export",                  {2,     2,    do_export}},
        {"hostname",                {1,     1,    do_hostname}},
        {"ifup",                    {1,     1,    do_ifup}},
@@ -942,5 +936,6 @@ BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
        {"wait_for_prop",           {2,     2,    do_wait_for_prop}},
        {"write",                   {2,     2,    do_write}},
    };
    // clang-format on
    return builtin_functions;
}
+2 −21
Original line number Diff line number Diff line
@@ -84,8 +84,6 @@ static time_t process_needs_restart_at;

const char *ENV[32];

static std::unique_ptr<Timer> waiting_for_exec(nullptr);

static int epoll_fd = -1;

static std::unique_ptr<Timer> waiting_for_prop(nullptr);
@@ -133,23 +131,6 @@ int add_environment(const char *key, const char *val)
    return -1;
}

bool start_waiting_for_exec()
{
    if (waiting_for_exec) {
        return false;
    }
    waiting_for_exec.reset(new Timer());
    return true;
}

void stop_waiting_for_exec()
{
    if (waiting_for_exec) {
        LOG(INFO) << "Wait for exec took " << *waiting_for_exec;
        waiting_for_exec.reset();
    }
}

bool start_waiting_for_property(const char *name, const char *value)
{
    if (waiting_for_prop) {
@@ -1323,10 +1304,10 @@ int main(int argc, char** argv) {
        // By default, sleep until something happens.
        int epoll_timeout_ms = -1;

        if (!(waiting_for_exec || waiting_for_prop)) {
        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
            am.ExecuteOneCommand();
        }
        if (!(waiting_for_exec || waiting_for_prop)) {
        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
            restart_processes();

            // If there's a process that needs restarting, wake up in time for that.
+0 −4
Original line number Diff line number Diff line
@@ -32,10 +32,6 @@ void register_epoll_handler(int fd, void (*fn)());

int add_environment(const char* key, const char* val);

bool start_waiting_for_exec();

void stop_waiting_for_exec();

bool start_waiting_for_property(const char *name, const char *value);

#endif  /* _INIT_INIT_H */
+58 −9
Original line number Diff line number Diff line
@@ -192,8 +192,8 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
}

void Service::NotifyStateChange(const std::string& new_state) const {
    if ((flags_ & SVC_EXEC) != 0) {
        // 'exec' commands don't have properties tracking their state.
    if ((flags_ & SVC_TEMPORARY) != 0) {
        // Services created by 'exec' are temporary and don't have properties tracking their state.
        return;
    }

@@ -260,7 +260,7 @@ void Service::SetProcessAttributes() {
    }
}

bool Service::Reap() {
void Service::Reap() {
    if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
        KillProcessGroup(SIGKILL);
    }
@@ -271,7 +271,10 @@ bool Service::Reap() {

    if (flags_ & SVC_EXEC) {
        LOG(INFO) << "SVC_EXEC pid " << pid_ << " finished...";
        return true;
    }

    if (flags_ & SVC_TEMPORARY) {
        return;
    }

    pid_ = 0;
@@ -286,7 +289,7 @@ bool Service::Reap() {
    // Disabled and reset processes do not get restarted automatically.
    if (flags_ & (SVC_DISABLED | SVC_RESET))  {
        NotifyStateChange("stopped");
        return false;
        return;
    }

    // If we crash > 4 times in 4 minutes, reboot into recovery.
@@ -310,7 +313,7 @@ bool Service::Reap() {
    onrestart_.ExecuteAllCommands();

    NotifyStateChange("restarting");
    return false;
    return;
}

void Service::DumpState() const {
@@ -578,6 +581,18 @@ bool Service::ParseLine(const std::vector<std::string>& args, std::string* err)
    return (this->*parser)(args, err);
}

bool Service::ExecStart(std::unique_ptr<Timer>* exec_waiter) {
    flags_ |= SVC_EXEC | SVC_ONESHOT;

    exec_waiter->reset(new Timer);

    if (!Start()) {
        exec_waiter->reset();
        return false;
    }
    return true;
}

bool Service::Start() {
    // Starting a service removes it from the disabled or reset state and
    // immediately takes it out of the restarting state if it was in there.
@@ -864,6 +879,35 @@ 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) {
    // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS...
    // SECLABEL can be a - to denote default
@@ -887,7 +931,7 @@ Service* ServiceManager::MakeExecOneshotService(const std::vector<std::string>&

    exec_count_++;
    std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str());
    unsigned flags = SVC_EXEC | SVC_ONESHOT;
    unsigned flags = SVC_EXEC | SVC_ONESHOT | SVC_TEMPORARY;
    CapSet no_capabilities;
    unsigned namespace_flags = 0;

@@ -1027,8 +1071,13 @@ bool ServiceManager::ReapOneProcess() {
        return true;
    }

    if (svc->Reap()) {
        stop_waiting_for_exec();
    svc->Reap();

    if (svc->flags() & SVC_EXEC) {
        LOG(INFO) << "Wait for exec took " << *exec_waiter_;
        exec_waiter_.reset();
    }
    if (svc->flags() & SVC_TEMPORARY) {
        RemoveService(*svc);
    }

Loading