From ac4c2f890f601d2f395c8f8cc2f90e20377d7da8 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Mon, 8 Jun 2020 23:47:10 +0300 Subject: SystemServer: Add support for multi-instance services For this kind of services, there's no single PID of a running instance; there may be multiple, or no instances of the service running at any time. No keepalive functionality is available in this mode, since "alive" doesn't make sense for multi-instance services. At the moment, there's no way to actually create multiple instances of a service; this is going to be added in the next commit. --- Services/SystemServer/Service.cpp | 22 ++++++++++++++++------ Services/SystemServer/Service.h | 4 +++- Services/SystemServer/main.cpp | 4 ++-- 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'Services') diff --git a/Services/SystemServer/Service.cpp b/Services/SystemServer/Service.cpp index 790ce58c25..d4fe6a98fd 100644 --- a/Services/SystemServer/Service.cpp +++ b/Services/SystemServer/Service.cpp @@ -180,12 +180,12 @@ void Service::spawn() dbg() << "Spawning " << name(); m_run_timer.start(); - m_pid = fork(); + pid_t pid = fork(); - if (m_pid < 0) { + if (pid < 0) { perror("fork"); - ASSERT_NOT_REACHED(); - } else if (m_pid == 0) { + dbg() << "Failed to spawn " << name() << ". Sucks, dude :("; + } else if (pid == 0) { // We are the child. if (!m_working_directory.is_null()) { @@ -258,15 +258,17 @@ void Service::spawn() rc = execv(argv[0], argv); perror("exec"); ASSERT_NOT_REACHED(); - } else { + } else if (!m_multi_instance) { // We are the parent. - s_service_map.set(m_pid, this); + m_pid = pid; + s_service_map.set(pid, this); } } void Service::did_exit(int exit_code) { ASSERT(m_pid > 0); + ASSERT(!m_multi_instance); dbg() << "Service " << name() << " has exited with exit code " << exit_code; @@ -327,8 +329,15 @@ Service::Service(const Core::ConfigFile& config, const StringView& name) m_working_directory = config.read_entry(name, "WorkingDirectory"); m_environment = config.read_entry(name, "Environment").split(' '); m_boot_modes = config.read_entry(name, "BootModes", "graphical").split(','); + m_multi_instance = config.read_bool_entry(name, "MultiInstance"); m_socket_path = config.read_entry(name, "Socket"); + + // Lazy requires Socket. + ASSERT(!m_lazy || !m_socket_path.is_null()); + // MultiInstance doesn't work with KeepAlive. + ASSERT(!m_multi_instance || !m_keep_alive); + if (!m_socket_path.is_null() && is_enabled()) { auto socket_permissions_string = config.read_entry(name, "SocketPermissions", "0600"); m_socket_permissions = strtol(socket_permissions_string.characters(), nullptr, 8) & 04777; @@ -369,6 +378,7 @@ void Service::save_to(JsonObject& json) json.set("user", m_user); json.set("uid", m_uid); json.set("gid", m_gid); + json.set("multi_instance", m_multi_instance); if (m_pid > 0) json.set("pid", m_pid); diff --git a/Services/SystemServer/Service.h b/Services/SystemServer/Service.h index b7cf1679a5..bfe143351c 100644 --- a/Services/SystemServer/Service.h +++ b/Services/SystemServer/Service.h @@ -73,10 +73,12 @@ private: String m_working_directory; // Boot modes to run this service in. By default, this is the graphical mode. Vector m_boot_modes; + // Whether several instances of this service can run at once. + bool m_multi_instance { false }; // Environment variables to pass to the service. Vector m_environment; - // PID of the running instance of this service. + // For single-instance services, PID of the running instance of this service. pid_t m_pid { -1 }; // An open fd to the socket. int m_socket_fd { -1 }; diff --git a/Services/SystemServer/main.cpp b/Services/SystemServer/main.cpp index e19b4891a1..fe355807ec 100644 --- a/Services/SystemServer/main.cpp +++ b/Services/SystemServer/main.cpp @@ -47,10 +47,10 @@ static void sigchld_handler(int) if (!pid) return; - dbg() << "Reaped child with pid " << pid; + dbg() << "Reaped child with pid " << pid << ", exist status " << status; Service* service = Service::find_by_pid(pid); if (service == nullptr) { - dbg() << "There was no service with this pid, what is going on?"; + // This can happen for multi-instance services. return; } -- cgit v1.2.3