mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:27:35 +00:00
SystemServer: Add support for accepting socket connections :^)
You can now ask SystemServer to not only listen for connections on the socket, but to actually accept them, and to spawn an instance of the service for each client connection. In this case, it's the accepted, not listening, socket that the service processes will receive using socket takeover. This mode obviously requires the service to be a multi-instance service.
This commit is contained in:
parent
ac4c2f890f
commit
701994bfd1
2 changed files with 35 additions and 10 deletions
|
@ -158,11 +158,26 @@ void Service::setup_notifier()
|
|||
|
||||
m_socket_notifier = Core::Notifier::construct(m_socket_fd, Core::Notifier::Event::Read, this);
|
||||
m_socket_notifier->on_ready_to_read = [this] {
|
||||
dbg() << "Ready to read on behalf of " << name();
|
||||
handle_socket_connection();
|
||||
};
|
||||
}
|
||||
|
||||
void Service::handle_socket_connection()
|
||||
{
|
||||
dbg() << "Ready to read on behalf of " << name();
|
||||
if (m_accept_socket_connections) {
|
||||
int accepted_fd = accept(m_socket_fd, nullptr, nullptr);
|
||||
if (accepted_fd < 0) {
|
||||
perror("accept");
|
||||
return;
|
||||
}
|
||||
spawn(accepted_fd);
|
||||
close(accepted_fd);
|
||||
} else {
|
||||
remove_child(*m_socket_notifier);
|
||||
m_socket_notifier = nullptr;
|
||||
spawn();
|
||||
};
|
||||
spawn(m_socket_fd);
|
||||
}
|
||||
}
|
||||
|
||||
void Service::activate()
|
||||
|
@ -172,10 +187,10 @@ void Service::activate()
|
|||
if (m_lazy)
|
||||
setup_notifier();
|
||||
else
|
||||
spawn();
|
||||
spawn(m_socket_fd);
|
||||
}
|
||||
|
||||
void Service::spawn()
|
||||
void Service::spawn(int socket_fd)
|
||||
{
|
||||
dbg() << "Spawning " << name();
|
||||
|
||||
|
@ -231,11 +246,12 @@ void Service::spawn()
|
|||
dup2(STDIN_FILENO, STDERR_FILENO);
|
||||
}
|
||||
|
||||
if (!m_socket_path.is_null()) {
|
||||
ASSERT(m_socket_fd > 2);
|
||||
dup2(m_socket_fd, 3);
|
||||
if (socket_fd >= 0) {
|
||||
ASSERT(!m_socket_path.is_null());
|
||||
ASSERT(socket_fd > 2);
|
||||
dup2(socket_fd, 3);
|
||||
// The new descriptor is !CLOEXEC here.
|
||||
// This is true even if m_socket_fd == 3.
|
||||
// This is true even if socket_fd == 3.
|
||||
setenv("SOCKET_TAKEOVER", "1", true);
|
||||
}
|
||||
|
||||
|
@ -330,11 +346,14 @@ Service::Service(const Core::ConfigFile& config, const StringView& name)
|
|||
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_accept_socket_connections = config.read_bool_entry(name, "AcceptSocketConnections");
|
||||
|
||||
m_socket_path = config.read_entry(name, "Socket");
|
||||
|
||||
// Lazy requires Socket.
|
||||
ASSERT(!m_lazy || !m_socket_path.is_null());
|
||||
// AcceptSocketConnections always requires Socket, Lazy, and MultiInstance.
|
||||
ASSERT(!m_accept_socket_connections || (!m_socket_path.is_null() && m_lazy && m_multi_instance));
|
||||
// MultiInstance doesn't work with KeepAlive.
|
||||
ASSERT(!m_multi_instance || !m_keep_alive);
|
||||
|
||||
|
@ -379,6 +398,7 @@ void Service::save_to(JsonObject& json)
|
|||
json.set("uid", m_uid);
|
||||
json.set("gid", m_gid);
|
||||
json.set("multi_instance", m_multi_instance);
|
||||
json.set("accept_socket_connections", m_accept_socket_connections);
|
||||
|
||||
if (m_pid > 0)
|
||||
json.set("pid", m_pid);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue