LibIPC: Move early fd deallocation workaround to the transport layer

Reimplements c3121c9d at the transport layer, allowing us to solve the
same problem once, in a single place, for both the LibIPC connection and
MessagePort. This avoids exposing a workaround for a macOS specific Unix
domain socket issue to higher abstraction layers.
This commit is contained in:
Aliaksandr Kalenik 2025-04-07 23:41:24 +02:00 committed by Alexander Kalenik
commit ab35325003
Notes: github-actions[bot] 2025-04-08 19:10:45 +00:00
7 changed files with 78 additions and 128 deletions

View file

@ -28,14 +28,9 @@ class ConnectionBase : public Core::EventReceiver {
public:
virtual ~ConnectionBase() override;
enum class MessageNeedsAcknowledgement {
No,
Yes,
};
[[nodiscard]] bool is_open() const;
ErrorOr<void> post_message(Message const&);
ErrorOr<void> post_message(u32 endpoint_magic, MessageBuffer, MessageNeedsAcknowledgement = MessageNeedsAcknowledgement::Yes);
ErrorOr<void> post_message(u32 endpoint_magic, MessageBuffer);
void shutdown();
virtual void die() { }
@ -43,7 +38,7 @@ public:
Transport& transport() { return m_transport; }
protected:
explicit ConnectionBase(IPC::Stub&, Transport, u32 local_endpoint_magic, u32 peer_endpoint_magic);
explicit ConnectionBase(IPC::Stub&, Transport, u32 local_endpoint_magic);
virtual void may_have_become_unresponsive() { }
virtual void did_become_responsive() { }
@ -65,38 +60,23 @@ protected:
Vector<NonnullOwnPtr<Message>> m_unprocessed_messages;
u32 m_local_endpoint_magic { 0 };
u32 m_peer_endpoint_magic { 0 };
struct MessageToSend {
MessageBuffer buffer;
MessageNeedsAcknowledgement needs_acknowledgement { MessageNeedsAcknowledgement::Yes };
};
struct SendQueue : public AtomicRefCounted<SendQueue> {
AK::SinglyLinkedList<MessageToSend> messages;
AK::SinglyLinkedList<MessageBuffer> messages;
Threading::Mutex mutex;
Threading::ConditionVariable condition { mutex };
bool running { true };
};
// After a message is sent, it is moved to the acknowledgement wait queue until an acknowledgement is received from the peer.
// This is necessary to handle a specific behavior of the macOS kernel, which may prematurely garbage-collect the file
// descriptor contained in the message before the peer receives it. https://openradar.me/9477351
struct AcknowledgementWaitQueue : public AtomicRefCounted<AcknowledgementWaitQueue> {
AK::SinglyLinkedList<MessageBuffer> messages;
Threading::Mutex mutex;
};
RefPtr<Threading::Thread> m_send_thread;
RefPtr<SendQueue> m_send_queue;
RefPtr<AcknowledgementWaitQueue> m_acknowledgement_wait_queue;
};
template<typename LocalEndpoint, typename PeerEndpoint>
class Connection : public ConnectionBase {
public:
Connection(IPC::Stub& local_stub, Transport transport)
: ConnectionBase(local_stub, move(transport), LocalEndpoint::static_magic(), PeerEndpoint::static_magic())
: ConnectionBase(local_stub, move(transport), LocalEndpoint::static_magic())
{
}