1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 14:25:06 +00:00

Kernel: Give each FileDescriptor a chance to co-open sockets.

Track how many fds are open for a socket's Accepted and Connected roles.
This allows fork() to clone a socket fd without a subsequent close() walking
all over the parent process's fd.
This commit is contained in:
Andreas Kling 2019-02-17 11:00:35 +01:00
parent b0be3299b5
commit d5f515cf6c
6 changed files with 51 additions and 27 deletions

View file

@ -106,23 +106,34 @@ bool LocalSocket::connect(const sockaddr* address, socklen_t address_size, int&
return true;
}
void LocalSocket::close(SocketRole role)
void LocalSocket::attach_fd(SocketRole role)
{
if (role == SocketRole::Accepted)
m_server_closed = true;
else if (role == SocketRole::Connected)
m_client_closed = true;
if (role == SocketRole::Accepted) {
++m_accepted_fds_open;
} else if (role == SocketRole::Connected) {
++m_connected_fds_open;
}
}
void LocalSocket::detach_fd(SocketRole role)
{
if (role == SocketRole::Accepted) {
ASSERT(m_accepted_fds_open);
--m_accepted_fds_open;
} else if (role == SocketRole::Connected) {
ASSERT(m_connected_fds_open);
--m_connected_fds_open;
}
}
bool LocalSocket::can_read(SocketRole role) const
{
if (m_bound && is_listening())
if (role == SocketRole::Listener)
return can_accept();
if (role == SocketRole::Accepted)
return m_client_closed || !m_for_server.is_empty();
else if (role == SocketRole::Connected)
return m_server_closed || !m_for_client.is_empty();
return !m_connected_fds_open || !m_for_server.is_empty();
if (role == SocketRole::Connected)
return !m_accepted_fds_open || !m_for_client.is_empty();
ASSERT_NOT_REACHED();
}
@ -130,7 +141,7 @@ ssize_t LocalSocket::read(SocketRole role, byte* buffer, size_t size)
{
if (role == SocketRole::Accepted)
return m_for_server.read(buffer, size);
else if (role == SocketRole::Connected)
if (role == SocketRole::Connected)
return m_for_client.read(buffer, size);
ASSERT_NOT_REACHED();
}
@ -138,11 +149,12 @@ ssize_t LocalSocket::read(SocketRole role, byte* buffer, size_t size)
ssize_t LocalSocket::write(SocketRole role, const byte* data, size_t size)
{
if (role == SocketRole::Accepted) {
if (m_client_closed)
if (!m_accepted_fds_open)
return -EPIPE;
return m_for_client.write(data, size);
} else if (role == SocketRole::Connected) {
if (m_client_closed)
}
if (role == SocketRole::Connected) {
if (!m_connected_fds_open)
return -EPIPE;
return m_for_server.write(data, size);
}
@ -152,8 +164,8 @@ ssize_t LocalSocket::write(SocketRole role, const byte* data, size_t size)
bool LocalSocket::can_write(SocketRole role) const
{
if (role == SocketRole::Accepted)
return m_client_closed || m_for_client.bytes_in_write_buffer() < 4096;
else if (role == SocketRole::Connected)
return m_server_closed || m_for_server.bytes_in_write_buffer() < 4096;
return !m_connected_fds_open || m_for_client.bytes_in_write_buffer() < 4096;
if (role == SocketRole::Connected)
return !m_accepted_fds_open || m_for_server.bytes_in_write_buffer() < 4096;
ASSERT_NOT_REACHED();
}