ladybird/Libraries/LibCore/SystemServerTakeover.cpp
Andreas Kling 164ed80244 Meta: Enable exit-time destructor warnings for libraries
Enable -Wexit-time-destructors for all in-tree library targets and
update process-lifetime library statics so they no longer register
exit-time destructors. Long-lived caches, lookup tables, singleton
registries, and generated constants now use NeverDestroyed or leaked
references where the data is intended to live until process exit.

Update LibWeb, LibLine, and the binding generators so regenerated
sources follow the same rule instead of reintroducing destructed
statics.
2026-06-04 19:20:49 +02:00

77 lines
2.2 KiB
C++

/*
* Copyright (c) 2022, sin-ack <sin-ack@protonmail.com>
* Copyright (c) 2025, stasoid <stasoid@yahoo.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "SystemServerTakeover.h"
#include <AK/NeverDestroyed.h>
#include <LibCore/Environment.h>
#include <LibCore/Socket.h>
#include <LibCore/System.h>
namespace Core {
bool s_overtaken_sockets_parsed { false };
static auto& overtaken_sockets()
{
static NeverDestroyed<HashMap<ByteString, int>> sockets;
return *sockets;
}
static void parse_sockets_from_system_server()
{
VERIFY(!s_overtaken_sockets_parsed);
constexpr auto socket_takeover = "SOCKET_TAKEOVER"sv;
auto sockets = Environment::get(socket_takeover);
if (!sockets.has_value()) {
s_overtaken_sockets_parsed = true;
return;
}
for (auto socket : sockets->split_view(';')) {
auto params = socket.split_view(':');
VERIFY(params.size() == 2);
overtaken_sockets().set(params[0].to_byte_string(), params[1].to_number<int>().value());
}
s_overtaken_sockets_parsed = true;
// We wouldn't want our children to think we're passing
// them a socket either, so unset the env variable.
MUST(Environment::unset(socket_takeover));
}
ErrorOr<NonnullOwnPtr<Core::LocalSocket>> take_over_socket_from_system_server(ByteString const& socket_path)
{
if (!s_overtaken_sockets_parsed)
parse_sockets_from_system_server();
int fd;
if (socket_path.is_empty()) {
// We want the first (and only) socket.
VERIFY(overtaken_sockets().size() == 1);
fd = overtaken_sockets().begin()->value;
} else {
auto it = overtaken_sockets().find(socket_path);
if (it == overtaken_sockets().end())
return Error::from_string_literal("Non-existent socket requested");
fd = it->value;
}
// Sanity check: it has to be a socket.
if (!System::is_socket(fd))
return Error::from_string_literal("The fd or handle we got from SystemServer is not a socket");
auto socket = TRY(Core::LocalSocket::adopt_fd(fd));
// It had to be !CLOEXEC for obvious reasons, but we
// don't need it to be !CLOEXEC anymore, so set the
// CLOEXEC flag now.
TRY(socket->set_close_on_exec(true));
return socket;
}
}