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

Commit adc2a7c5 authored by Tom Cherry's avatar Tom Cherry Committed by Android (Google) Code Review
Browse files

Merge changes Ice773436,Ib8a4835c into rvc-dev

* changes:
  init: handle property messages asynchronously #2
  Revert "init: handle property service callbacks asynchronously"
parents e3a22ca1 0c19d6c9
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ init_common_sources = [
    "rlimit_parser.cpp",
    "service.cpp",
    "service_list.cpp",
    "service_lock.cpp",
    "service_parser.cpp",
    "service_utils.cpp",
    "subcontext.cpp",
+0 −15
Original line number Diff line number Diff line
@@ -151,7 +151,6 @@ static Result<void> reboot_into_recovery(const std::vector<std::string>& options

template <typename F>
static void ForEachServiceInClass(const std::string& classname, F function) {
    auto lock = std::lock_guard{service_lock};
    for (const auto& service : ServiceList::GetInstance()) {
        if (service->classnames().count(classname)) std::invoke(function, service);
    }
@@ -163,7 +162,6 @@ static Result<void> do_class_start(const BuiltinArguments& args) {
        return {};
    // Starting a class does not start services which are explicitly disabled.
    // They must  be started individually.
    auto lock = std::lock_guard{service_lock};
    for (const auto& service : ServiceList::GetInstance()) {
        if (service->classnames().count(args[1])) {
            if (auto result = service->StartIfNotDisabled(); !result.ok()) {
@@ -186,7 +184,6 @@ static Result<void> do_class_start_post_data(const BuiltinArguments& args) {
        // stopped either.
        return {};
    }
    auto lock = std::lock_guard{service_lock};
    for (const auto& service : ServiceList::GetInstance()) {
        if (service->classnames().count(args[1])) {
            if (auto result = service->StartIfPostData(); !result.ok()) {
@@ -237,7 +234,6 @@ static Result<void> do_domainname(const BuiltinArguments& args) {
}

static Result<void> do_enable(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    Service* svc = ServiceList::GetInstance().FindService(args[1]);
    if (!svc) return Error() << "Could not find service";

@@ -249,7 +245,6 @@ static Result<void> do_enable(const BuiltinArguments& args) {
}

static Result<void> do_exec(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    auto service = Service::MakeTemporaryOneshotService(args.args);
    if (!service.ok()) {
        return Error() << "Could not create exec service: " << service.error();
@@ -263,7 +258,6 @@ static Result<void> do_exec(const BuiltinArguments& args) {
}

static Result<void> do_exec_background(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    auto service = Service::MakeTemporaryOneshotService(args.args);
    if (!service.ok()) {
        return Error() << "Could not create exec background service: " << service.error();
@@ -277,7 +271,6 @@ static Result<void> do_exec_background(const BuiltinArguments& args) {
}

static Result<void> do_exec_start(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    Service* service = ServiceList::GetInstance().FindService(args[1]);
    if (!service) {
        return Error() << "Service not found";
@@ -347,7 +340,6 @@ static Result<void> do_insmod(const BuiltinArguments& args) {
}

static Result<void> do_interface_restart(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
    if (!svc) return Error() << "interface " << args[1] << " not found";
    svc->Restart();
@@ -355,7 +347,6 @@ static Result<void> do_interface_restart(const BuiltinArguments& args) {
}

static Result<void> do_interface_start(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
    if (!svc) return Error() << "interface " << args[1] << " not found";
    if (auto result = svc->Start(); !result.ok()) {
@@ -365,7 +356,6 @@ static Result<void> do_interface_start(const BuiltinArguments& args) {
}

static Result<void> do_interface_stop(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
    if (!svc) return Error() << "interface " << args[1] << " not found";
    svc->Stop();
@@ -750,7 +740,6 @@ static Result<void> do_setrlimit(const BuiltinArguments& args) {
}

static Result<void> do_start(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    Service* svc = ServiceList::GetInstance().FindService(args[1]);
    if (!svc) return Error() << "service " << args[1] << " not found";
    if (auto result = svc->Start(); !result.ok()) {
@@ -760,7 +749,6 @@ static Result<void> do_start(const BuiltinArguments& args) {
}

static Result<void> do_stop(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    Service* svc = ServiceList::GetInstance().FindService(args[1]);
    if (!svc) return Error() << "service " << args[1] << " not found";
    svc->Stop();
@@ -768,7 +756,6 @@ static Result<void> do_stop(const BuiltinArguments& args) {
}

static Result<void> do_restart(const BuiltinArguments& args) {
    auto lock = std::lock_guard{service_lock};
    Service* svc = ServiceList::GetInstance().FindService(args[1]);
    if (!svc) return Error() << "service " << args[1] << " not found";
    svc->Restart();
@@ -1124,7 +1111,6 @@ static Result<void> ExecWithFunctionOnFailure(const std::vector<std::string>& ar
            function(StringPrintf("Exec service failed, status %d", siginfo.si_status));
        }
    });
    auto lock = std::lock_guard{service_lock};
    if (auto result = (*service)->ExecStart(); !result.ok()) {
        function("ExecStart failed: " + result.error().message());
    }
@@ -1264,7 +1250,6 @@ static Result<void> parse_apex_configs() {
        }
        success &= parser.ParseConfigFile(c);
    }
    auto lock = std::lock_guard{service_lock};
    ServiceList::GetInstance().MarkServicesUpdate();
    if (success) {
        return {};
+56 −31
Original line number Diff line number Diff line
@@ -99,6 +99,15 @@ static int property_fd = -1;

static std::unique_ptr<Subcontext> subcontext;

struct PendingControlMessage {
    std::string message;
    std::string name;
    pid_t pid;
    int fd;
};
static std::mutex pending_control_messages_lock;
static std::queue<PendingControlMessage> pending_control_messages;

// Init epolls various FDs to wait for various inputs.  It previously waited on property changes
// with a blocking socket that contained the information related to the change, however, it was easy
// to fill that socket and deadlock the system.  Now we use locks to handle the property changes
@@ -120,7 +129,7 @@ static void InstallInitNotifier(Epoll* epoll) {
        }
    };

    if (auto result = epoll->RegisterHandler(epoll_fd, drain_socket); !result) {
    if (auto result = epoll->RegisterHandler(epoll_fd, drain_socket); !result.ok()) {
        LOG(FATAL) << result.error();
    }
}
@@ -238,7 +247,6 @@ static class ShutdownState {
} shutdown_state;

void DumpState() {
    auto lock = std::lock_guard{service_lock};
    ServiceList::GetInstance().DumpState();
    ActionManager::GetInstance().DumpState();
}
@@ -312,7 +320,6 @@ void PropertyChanged(const std::string& name, const std::string& value) {

static std::optional<boot_clock::time_point> HandleProcessActions() {
    std::optional<boot_clock::time_point> next_process_action_time;
    auto lock = std::lock_guard{service_lock};
    for (const auto& s : ServiceList::GetInstance()) {
        if ((s->flags() & SVC_RUNNING) && s->timeout_period()) {
            auto timeout_time = s->time_started() + *s->timeout_period();
@@ -341,7 +348,7 @@ static std::optional<boot_clock::time_point> HandleProcessActions() {
    return next_process_action_time;
}

static Result<void> DoControlStart(Service* service) REQUIRES(service_lock) {
static Result<void> DoControlStart(Service* service) {
    return service->Start();
}

@@ -350,7 +357,7 @@ static Result<void> DoControlStop(Service* service) {
    return {};
}

static Result<void> DoControlRestart(Service* service) REQUIRES(service_lock) {
static Result<void> DoControlRestart(Service* service) {
    service->Restart();
    return {};
}
@@ -384,7 +391,7 @@ static const std::map<std::string, ControlMessageFunction>& get_control_message_
    return control_message_functions;
}

bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t from_pid) {
bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
    const auto& map = get_control_message_map();
    const auto it = map.find(msg);

@@ -393,7 +400,7 @@ bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t
        return false;
    }

    std::string cmdline_path = StringPrintf("proc/%d/cmdline", from_pid);
    std::string cmdline_path = StringPrintf("proc/%d/cmdline", pid);
    std::string process_cmdline;
    if (ReadFileToString(cmdline_path, &process_cmdline)) {
        std::replace(process_cmdline.begin(), process_cmdline.end(), '\0', ' ');
@@ -404,8 +411,6 @@ bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t

    const ControlMessageFunction& function = it->second;

    auto lock = std::lock_guard{service_lock};

    Service* svc = nullptr;

    switch (function.target) {
@@ -423,22 +428,59 @@ bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t

    if (svc == nullptr) {
        LOG(ERROR) << "Control message: Could not find '" << name << "' for ctl." << msg
                   << " from pid: " << from_pid << " (" << process_cmdline << ")";
                   << " from pid: " << pid << " (" << process_cmdline << ")";
        return false;
    }

    if (auto result = function.action(svc); !result.ok()) {
        LOG(ERROR) << "Control message: Could not ctl." << msg << " for '" << name
                   << "' from pid: " << from_pid << " (" << process_cmdline
                   << "): " << result.error();
                   << "' from pid: " << pid << " (" << process_cmdline << "): " << result.error();
        return false;
    }

    LOG(INFO) << "Control message: Processed ctl." << msg << " for '" << name
              << "' from pid: " << from_pid << " (" << process_cmdline << ")";
              << "' from pid: " << pid << " (" << process_cmdline << ")";
    return true;
}

bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd) {
    auto lock = std::lock_guard{pending_control_messages_lock};
    if (pending_control_messages.size() > 100) {
        LOG(ERROR) << "Too many pending control messages, dropped '" << message << "' for '" << name
                   << "' from pid: " << pid;
        return false;
    }
    pending_control_messages.push({message, name, pid, fd});
    WakeEpoll();
    return true;
}

static void HandleControlMessages() {
    auto lock = std::unique_lock{pending_control_messages_lock};
    // Init historically would only execute handle one property message, including control messages
    // in each iteration of its main loop.  We retain this behavior here to prevent starvation of
    // other actions in the main loop.
    if (!pending_control_messages.empty()) {
        auto control_message = pending_control_messages.front();
        pending_control_messages.pop();
        lock.unlock();

        bool success = HandleControlMessage(control_message.message, control_message.name,
                                            control_message.pid);

        uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
        if (control_message.fd != -1) {
            TEMP_FAILURE_RETRY(send(control_message.fd, &response, sizeof(response), 0));
            close(control_message.fd);
        }
        lock.lock();
    }
    // If we still have items to process, make sure we wake back up to do so.
    if (!pending_control_messages.empty()) {
        WakeEpoll();
    }
}

static Result<void> wait_for_coldboot_done_action(const BuiltinArguments& args) {
    if (!prop_waiter_state.StartWaiting(kColdBootDoneProp, "true")) {
        LOG(FATAL) << "Could not wait for '" << kColdBootDoneProp << "'";
@@ -588,7 +630,6 @@ void HandleKeychord(const std::vector<int>& keycodes) {
    }

    auto found = false;
    auto lock = std::lock_guard{service_lock};
    for (const auto& service : ServiceList::GetInstance()) {
        auto svc = service.get();
        if (svc->keycodes() == keycodes) {
@@ -659,22 +700,6 @@ void SendLoadPersistentPropertiesMessage() {
    }
}

void SendStopSendingMessagesMessage() {
    auto init_message = InitMessage{};
    init_message.set_stop_sending_messages(true);
    if (auto result = SendMessage(property_fd, init_message); !result.ok()) {
        LOG(ERROR) << "Failed to send 'stop sending messages' message: " << result.error();
    }
}

void SendStartSendingMessagesMessage() {
    auto init_message = InitMessage{};
    init_message.set_start_sending_messages(true);
    if (auto result = SendMessage(property_fd, init_message); !result.ok()) {
        LOG(ERROR) << "Failed to send 'start sending messages' message: " << result.error();
    }
}

int SecondStageMain(int argc, char** argv) {
    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();
@@ -796,7 +821,6 @@ int SecondStageMain(int argc, char** argv) {
    Keychords keychords;
    am.QueueBuiltinAction(
            [&epoll, &keychords](const BuiltinArguments& args) -> Result<void> {
                auto lock = std::lock_guard{service_lock};
                for (const auto& svc : ServiceList::GetInstance()) {
                    keychords.Register(svc->keycodes());
                }
@@ -863,6 +887,7 @@ int SecondStageMain(int argc, char** argv) {
                (*function)();
            }
        }
        HandleControlMessages();
    }

    return 0;
+1 −3
Original line number Diff line number Diff line
@@ -38,11 +38,9 @@ void DumpState();
void ResetWaitForProp();

void SendLoadPersistentPropertiesMessage();
void SendStopSendingMessagesMessage();
void SendStartSendingMessagesMessage();

void PropertyChanged(const std::string& name, const std::string& value);
bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t from_pid);
bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd);

int SecondStageMain(int argc, char** argv);

+0 −1
Original line number Diff line number Diff line
@@ -167,7 +167,6 @@ service A something

    ServiceList service_list;
    TestInitText(init_script, BuiltinFunctionMap(), {}, &service_list);
    auto lock = std::lock_guard{service_lock};
    ASSERT_EQ(1, std::distance(service_list.begin(), service_list.end()));

    auto service = service_list.begin()->get();
Loading