Kernel: Fix how socket closing works

Sockets are now closed only when they are not referenced any more. This
allows child process to close socket and still keep it open for the
parent.
This commit is contained in:
2024-06-19 10:39:44 +03:00
parent d5daa46ab8
commit bce16cdd6e
9 changed files with 50 additions and 55 deletions

View File

@@ -56,12 +56,6 @@ namespace Kernel
return true;
}
void Inode::on_close()
{
LockGuard _(m_mutex);
on_close_impl();
}
BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name)
{
LockGuard _(m_mutex);

View File

@@ -63,39 +63,6 @@ namespace Kernel
{
ASSERT(!is_bound());
ASSERT(m_process == nullptr);
dprintln_if(DEBUG_TCP, "socket destroyed");
}
void TCPSocket::on_close_impl()
{
LockGuard _(m_mutex);
if (!is_bound())
return;
switch (m_state)
{
case State::Established:
break;
case State::SynSent:
set_connection_as_closed();
// fall through
case State::SynReceived:
case State::FinWait1:
case State::FinWait2:
case State::CloseWait:
case State::Closing:
case State::TimeWait:
case State::LastAck:
return;
case State::Closed: ASSERT_NOT_REACHED();
case State::Listen: ASSERT_NOT_REACHED();
}
m_state = State::FinWait1;
m_should_ack = true;
dprintln_if(DEBUG_TCP, "Initiated close");
}
BAN::ErrorOr<void> TCPSocket::connect_impl(const sockaddr* address, socklen_t address_len)
@@ -407,6 +374,38 @@ namespace Kernel
m_semaphore.unblock();
}
void TCPSocket::start_close_sequence()
{
LockGuard _(m_mutex);
if (!is_bound())
return;
switch (m_state)
{
case State::Established:
break;
case State::SynSent:
set_connection_as_closed();
return;
case State::SynReceived:
case State::FinWait1:
case State::FinWait2:
case State::CloseWait:
case State::Closing:
case State::TimeWait:
case State::LastAck:
return;
case State::Closed: ASSERT_NOT_REACHED();
case State::Listen: ASSERT_NOT_REACHED();
}
m_state = State::FinWait1;
m_should_ack = true;
dprintln_if(DEBUG_TCP, "Initiated close");
}
void TCPSocket::set_connection_as_closed()
{
@@ -427,13 +426,25 @@ namespace Kernel
static constexpr uint32_t retransmit_timeout_ms = 1000;
BAN::RefPtr<TCPSocket> keep_alive = this;
bool started_close_sequence = false;
while (m_process)
{
uint64_t current_ms = SystemTimer::get().ms_since_boot();
const uint64_t current_ms = SystemTimer::get().ms_since_boot();
if (m_state == State::TimeWait && current_ms >= m_time_wait_start_ms + 30'000)
{
set_connection_as_closed();
continue;
}
// This is the last instance
if (!started_close_sequence && ref_count() == 1)
{
start_close_sequence();
started_close_sequence = true;
continue;
}
{
LockGuard _(m_mutex);

View File

@@ -23,7 +23,7 @@ namespace Kernel
: NetworkSocket(network_layer, ino, inode_info)
{ }
void UDPSocket::on_close_impl()
UDPSocket::~UDPSocket()
{
if (is_bound())
m_network_layer.unbind_socket(this, m_port);

View File

@@ -47,7 +47,7 @@ namespace Kernel
}
}
void UnixDomainSocket::on_close_impl()
UnixDomainSocket::~UnixDomainSocket()
{
if (is_bound() && !is_bound_to_unused())
{

View File

@@ -317,8 +317,6 @@ namespace Kernel
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
((Pipe*)m_open_files[fd]->inode.ptr())->close_writing();
m_open_files[fd]->inode->on_close();
m_open_files[fd].clear();
return {};