mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 20:57:41 +00:00
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.
This commit is contained in:
parent
31b025fcfc
commit
ac4c2f890f
3 changed files with 21 additions and 9 deletions
|
@ -180,12 +180,12 @@ void Service::spawn()
|
||||||
dbg() << "Spawning " << name();
|
dbg() << "Spawning " << name();
|
||||||
|
|
||||||
m_run_timer.start();
|
m_run_timer.start();
|
||||||
m_pid = fork();
|
pid_t pid = fork();
|
||||||
|
|
||||||
if (m_pid < 0) {
|
if (pid < 0) {
|
||||||
perror("fork");
|
perror("fork");
|
||||||
ASSERT_NOT_REACHED();
|
dbg() << "Failed to spawn " << name() << ". Sucks, dude :(";
|
||||||
} else if (m_pid == 0) {
|
} else if (pid == 0) {
|
||||||
// We are the child.
|
// We are the child.
|
||||||
|
|
||||||
if (!m_working_directory.is_null()) {
|
if (!m_working_directory.is_null()) {
|
||||||
|
@ -258,15 +258,17 @@ void Service::spawn()
|
||||||
rc = execv(argv[0], argv);
|
rc = execv(argv[0], argv);
|
||||||
perror("exec");
|
perror("exec");
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
} else {
|
} else if (!m_multi_instance) {
|
||||||
// We are the parent.
|
// 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)
|
void Service::did_exit(int exit_code)
|
||||||
{
|
{
|
||||||
ASSERT(m_pid > 0);
|
ASSERT(m_pid > 0);
|
||||||
|
ASSERT(!m_multi_instance);
|
||||||
|
|
||||||
dbg() << "Service " << name() << " has exited with exit code " << exit_code;
|
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_working_directory = config.read_entry(name, "WorkingDirectory");
|
||||||
m_environment = config.read_entry(name, "Environment").split(' ');
|
m_environment = config.read_entry(name, "Environment").split(' ');
|
||||||
m_boot_modes = config.read_entry(name, "BootModes", "graphical").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");
|
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()) {
|
if (!m_socket_path.is_null() && is_enabled()) {
|
||||||
auto socket_permissions_string = config.read_entry(name, "SocketPermissions", "0600");
|
auto socket_permissions_string = config.read_entry(name, "SocketPermissions", "0600");
|
||||||
m_socket_permissions = strtol(socket_permissions_string.characters(), nullptr, 8) & 04777;
|
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("user", m_user);
|
||||||
json.set("uid", m_uid);
|
json.set("uid", m_uid);
|
||||||
json.set("gid", m_gid);
|
json.set("gid", m_gid);
|
||||||
|
json.set("multi_instance", m_multi_instance);
|
||||||
|
|
||||||
if (m_pid > 0)
|
if (m_pid > 0)
|
||||||
json.set("pid", m_pid);
|
json.set("pid", m_pid);
|
||||||
|
|
|
@ -73,10 +73,12 @@ private:
|
||||||
String m_working_directory;
|
String m_working_directory;
|
||||||
// Boot modes to run this service in. By default, this is the graphical mode.
|
// Boot modes to run this service in. By default, this is the graphical mode.
|
||||||
Vector<String> m_boot_modes;
|
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.
|
// Environment variables to pass to the service.
|
||||||
Vector<String> m_environment;
|
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 };
|
pid_t m_pid { -1 };
|
||||||
// An open fd to the socket.
|
// An open fd to the socket.
|
||||||
int m_socket_fd { -1 };
|
int m_socket_fd { -1 };
|
||||||
|
|
|
@ -47,10 +47,10 @@ static void sigchld_handler(int)
|
||||||
if (!pid)
|
if (!pid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dbg() << "Reaped child with pid " << pid;
|
dbg() << "Reaped child with pid " << pid << ", exist status " << status;
|
||||||
Service* service = Service::find_by_pid(pid);
|
Service* service = Service::find_by_pid(pid);
|
||||||
if (service == nullptr) {
|
if (service == nullptr) {
|
||||||
dbg() << "There was no service with this pid, what is going on?";
|
// This can happen for multi-instance services.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue