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

Commit 76af7e6a authored by Tom Cherry's avatar Tom Cherry
Browse files

init: log Service failures via Result<T>

Log Service failures via Result<T> such that their context can be
captured when interacting with services through builtin functions.

Test: boot bullhead
Change-Id: I4d99744d64008d4a06a404e3c9817182c6e177bc
parent 130e3d72
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -127,7 +127,9 @@ static Result<Success> do_enable(const std::vector<std::string>& args) {
    Service* svc = ServiceList::GetInstance().FindService(args[1]);
    if (!svc) return Error() << "Could not find service";

    if (!svc->Enable()) return Error() << "Could not enable service";
    if (auto result = svc->Enable(); !result) {
        return Error() << "Could not enable service: " << result.error();
    }

    return Success();
}
@@ -137,8 +139,8 @@ static Result<Success> do_exec(const std::vector<std::string>& args) {
    if (!service) {
        return Error() << "Could not create exec service";
    }
    if (!service->ExecStart()) {
        return Error() << "Could not start exec service";
    if (auto result = service->ExecStart(); !result) {
        return Error() << "Could not start exec service: " << result.error();
    }

    ServiceList::GetInstance().AddService(std::move(service));
@@ -151,8 +153,8 @@ static Result<Success> do_exec_start(const std::vector<std::string>& args) {
        return Error() << "Service not found";
    }

    if (!service->ExecStart()) {
        return Error() << "Could not start Service";
    if (auto result = service->ExecStart(); !result) {
        return Error() << "Could not start exec service: " << result.error();
    }

    return Success();
@@ -583,7 +585,9 @@ static Result<Success> do_setrlimit(const std::vector<std::string>& args) {
static Result<Success> do_start(const std::vector<std::string>& args) {
    Service* svc = ServiceList::GetInstance().FindService(args[1]);
    if (!svc) return Error() << "service " << args[1] << " not found";
    if (!svc->Start()) return Error() << "failed to start service";
    if (auto result = svc->Start(); !result) {
        return Error() << "Could not start service: " << result.error();
    }
    return Success();
}

+29 −32
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ using android::base::WriteStringToFile;
namespace android {
namespace init {

static std::string ComputeContextFromExecutable(std::string& service_name,
static Result<std::string> ComputeContextFromExecutable(std::string& service_name,
                                                        const std::string& service_path) {
    std::string computed_context;

@@ -65,14 +65,12 @@ static std::string ComputeContextFromExecutable(std::string& service_name,
    char* raw_filecon = nullptr;

    if (getcon(&raw_con) == -1) {
        LOG(ERROR) << "could not get context while starting '" << service_name << "'";
        return "";
        return Error() << "Could not get security context";
    }
    std::unique_ptr<char> mycon(raw_con);

    if (getfilecon(service_path.c_str(), &raw_filecon) == -1) {
        LOG(ERROR) << "could not get file context while starting '" << service_name << "'";
        return "";
        return Error() << "Could not get file context";
    }
    std::unique_ptr<char> filecon(raw_filecon);

@@ -84,12 +82,10 @@ static std::string ComputeContextFromExecutable(std::string& service_name,
        free(new_con);
    }
    if (rc == 0 && computed_context == mycon.get()) {
        LOG(ERROR) << "service " << service_name << " does not have a SELinux domain defined";
        return "";
        return Error() << "Service does not have an SELinux domain defined";
    }
    if (rc < 0) {
        LOG(ERROR) << "could not get context while starting '" << service_name << "'";
        return "";
        return Error() << "Could not get process context";
    }
    return computed_context;
}
@@ -629,16 +625,16 @@ Result<Success> Service::ParseLine(const std::vector<std::string>& args) {
    static const OptionParserMap parser_map;
    auto parser = parser_map.FindFunction(args);

    if (!parser) return Error() << parser.error();
    if (!parser) return parser.error();

    return std::invoke(*parser, this, args);
}

bool Service::ExecStart() {
Result<Success> Service::ExecStart() {
    flags_ |= SVC_ONESHOT;

    if (!Start()) {
        return false;
    if (auto result = Start(); !result) {
        return result;
    }

    flags_ |= SVC_EXEC;
@@ -648,10 +644,10 @@ bool Service::ExecStart() {
              << supp_gids_.size() << " context " << (!seclabel_.empty() ? seclabel_ : "default")
              << ") started; waiting...";

    return true;
    return Success();
}

bool Service::Start() {
Result<Success> 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.
    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
@@ -660,7 +656,8 @@ bool Service::Start() {
    // process of exiting, we've ensured that they will immediately restart
    // on exit, unless they are ONESHOT.
    if (flags_ & SVC_RUNNING) {
        return false;
        // It is not an error to try to start a service that is already running.
        return Success();
    }

    bool needs_console = (flags_ & SVC_CONSOLE);
@@ -673,28 +670,27 @@ bool Service::Start() {
        // properly registered for the device node
        int console_fd = open(console_.c_str(), O_RDWR | O_CLOEXEC);
        if (console_fd < 0) {
            PLOG(ERROR) << "service '" << name_ << "' couldn't open console '" << console_ << "'";
            flags_ |= SVC_DISABLED;
            return false;
            return ErrnoError() << "Couldn't open console '" << console_ << "'";
        }
        close(console_fd);
    }

    struct stat sb;
    if (stat(args_[0].c_str(), &sb) == -1) {
        PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'";
        flags_ |= SVC_DISABLED;
        return false;
        return ErrnoError() << "Cannot find '" << args_[0] << "'";
    }

    std::string scon;
    if (!seclabel_.empty()) {
        scon = seclabel_;
    } else {
        scon = ComputeContextFromExecutable(name_, args_[0]);
        if (scon == "") {
            return false;
        auto result = ComputeContextFromExecutable(name_, args_[0]);
        if (!result) {
            return result.error();
        }
        scon = *result;
    }

    LOG(INFO) << "starting service '" << name_ << "'...";
@@ -779,9 +775,8 @@ bool Service::Start() {
    }

    if (pid < 0) {
        PLOG(ERROR) << "failed to fork for '" << name_ << "'";
        pid_ = 0;
        return false;
        return ErrnoError() << "Failed to fork";
    }

    if (oom_score_adjust_ != -1000) {
@@ -823,24 +818,24 @@ bool Service::Start() {
    }

    NotifyStateChange("running");
    return true;
    return Success();
}

bool Service::StartIfNotDisabled() {
Result<Success> Service::StartIfNotDisabled() {
    if (!(flags_ & SVC_DISABLED)) {
        return Start();
    } else {
        flags_ |= SVC_DISABLED_START;
    }
    return true;
    return Success();
}

bool Service::Enable() {
Result<Success> Service::Enable() {
    flags_ &= ~(SVC_DISABLED | SVC_RC_DISABLED);
    if (flags_ & SVC_DISABLED_START) {
        return Start();
    }
    return true;
    return Success();
}

void Service::Reset() {
@@ -866,7 +861,9 @@ void Service::Restart() {
        StopOrReset(SVC_RESTART);
    } else if (!(flags_ & SVC_RESTARTING)) {
        /* Just start the service since it's not running. */
        Start();
        if (auto result = Start(); !result) {
            LOG(ERROR) << "Could not restart '" << name_ << "': " << result.error();
        }
    } /* else: Service is restarting anyways. */
}

+4 −4
Original line number Diff line number Diff line
@@ -70,10 +70,10 @@ class Service {

    bool IsRunning() { return (flags_ & SVC_RUNNING) != 0; }
    Result<Success> ParseLine(const std::vector<std::string>& args);
    bool ExecStart();
    bool Start();
    bool StartIfNotDisabled();
    bool Enable();
    Result<Success> ExecStart();
    Result<Success> Start();
    Result<Success> StartIfNotDisabled();
    Result<Success> Enable();
    void Reset();
    void Stop();
    void Terminate();