summaryrefslogtreecommitdiff
path: root/Services
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@serenityos.org>2020-06-08 23:47:10 +0300
committerAndreas Kling <kling@serenityos.org>2020-06-09 21:12:34 +0200
commitac4c2f890f601d2f395c8f8cc2f90e20377d7da8 (patch)
treecc680f1c498becbc7b64c15c105e2e859bd9df66 /Services
parent31b025fcfc19752db62713c08cb284060b71ad5b (diff)
downloadserenity-ac4c2f890f601d2f395c8f8cc2f90e20377d7da8.zip
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.
Diffstat (limited to 'Services')
-rw-r--r--Services/SystemServer/Service.cpp22
-rw-r--r--Services/SystemServer/Service.h4
-rw-r--r--Services/SystemServer/main.cpp4
3 files changed, 21 insertions, 9 deletions
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<String> 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<String> 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;
}