mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 01:35:08 +02:00
Previously, the bootstrap handshake used a two-state machine (WaitingForPorts / WaitingForReplyPort) to handle a race: the parent registering transport ports and the child sending a bootstrap request could arrive in either order, so whichever came first stored its half and the second completed the handshake. Eliminate the race by holding a mutex across spawn() and register_child_transport(). Since the child cannot send a bootstrap request before it exists, and the lock isn't released until its transport is registered, handle_bootstrap_request() is guaranteed to find the entry. This reduces the pending map to a simple pid-to-ports lookup and collapses the two-variant state into two straightforward branches: known child, or on-demand (non-child) caller like WebDriver.
61 lines
1.9 KiB
C++
61 lines
1.9 KiB
C++
/*
|
|
* Copyright (c) 2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/HashMap.h>
|
|
#include <AK/Platform.h>
|
|
#include <AK/StringView.h>
|
|
#include <AK/Variant.h>
|
|
|
|
#if !defined(AK_OS_MACH)
|
|
# error "TransportBootstrapMach is only available on Mach platforms"
|
|
#endif
|
|
|
|
#include <LibCore/MachPort.h>
|
|
#include <LibThreading/Mutex.h>
|
|
|
|
namespace IPC {
|
|
|
|
struct TransportBootstrapMachPorts {
|
|
Core::MachPort receive_right;
|
|
Core::MachPort send_right;
|
|
};
|
|
|
|
ErrorOr<TransportBootstrapMachPorts> bootstrap_transport_from_mach_server(StringView server_name);
|
|
ErrorOr<TransportBootstrapMachPorts> bootstrap_transport_from_server_port(Core::MachPort const& server_port);
|
|
|
|
class TransportBootstrapMachServer {
|
|
AK_MAKE_NONCOPYABLE(TransportBootstrapMachServer);
|
|
|
|
public:
|
|
TransportBootstrapMachServer() = default;
|
|
|
|
struct ChildTransportHandled {
|
|
};
|
|
struct OnDemandTransport {
|
|
TransportBootstrapMachPorts ports;
|
|
};
|
|
using BootstrapRequestResult = Variant<ChildTransportHandled, OnDemandTransport>;
|
|
|
|
// Hold this lock across process spawn and child transport registration so a
|
|
// child bootstrap request cannot observe an unregistered pid.
|
|
Threading::Mutex& child_registration_lock() { return m_child_registration_mutex; }
|
|
|
|
// Must be called while holding child_registration_lock().
|
|
void register_child_transport(pid_t, TransportBootstrapMachPorts);
|
|
ErrorOr<BootstrapRequestResult> handle_bootstrap_request(pid_t, Core::MachPort reply_port);
|
|
|
|
private:
|
|
static void send_transport_ports_to_child(Core::MachPort reply_port, TransportBootstrapMachPorts ports);
|
|
static ErrorOr<TransportBootstrapMachPorts> create_on_demand_local_transport(Core::MachPort reply_port);
|
|
|
|
Threading::Mutex m_child_registration_mutex;
|
|
HashMap<pid_t, TransportBootstrapMachPorts> m_child_transports;
|
|
};
|
|
|
|
}
|