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:
parent
d5daa46ab8
commit
bce16cdd6e
|
@ -86,8 +86,6 @@ namespace Kernel
|
||||||
virtual bool is_pipe() const { return false; }
|
virtual bool is_pipe() const { return false; }
|
||||||
virtual bool is_tty() const { return false; }
|
virtual bool is_tty() const { return false; }
|
||||||
|
|
||||||
void on_close();
|
|
||||||
|
|
||||||
// Directory API
|
// Directory API
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView);
|
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView);
|
||||||
BAN::ErrorOr<size_t> list_next_inodes(off_t, struct dirent* list, size_t list_size);
|
BAN::ErrorOr<size_t> list_next_inodes(off_t, struct dirent* list, size_t list_size);
|
||||||
|
@ -122,8 +120,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> ioctl(int request, void* arg);
|
BAN::ErrorOr<long> ioctl(int request, void* arg);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void on_close_impl() {}
|
|
||||||
|
|
||||||
// Directory API
|
// Directory API
|
||||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
|
|
|
@ -49,8 +49,6 @@ namespace Kernel
|
||||||
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
|
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void on_close_impl() override;
|
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||||
|
|
||||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr_storage& sender) override;
|
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr_storage& sender) override;
|
||||||
|
@ -111,6 +109,7 @@ namespace Kernel
|
||||||
TCPSocket(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
TCPSocket(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
||||||
void process_task();
|
void process_task();
|
||||||
|
|
||||||
|
void start_close_sequence();
|
||||||
void set_connection_as_closed();
|
void set_connection_as_closed();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -33,8 +33,6 @@ namespace Kernel
|
||||||
protected:
|
protected:
|
||||||
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr_storage& sender) override;
|
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr_storage& sender) override;
|
||||||
|
|
||||||
virtual void on_close_impl() override;
|
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
|
virtual BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
|
||||||
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override;
|
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override;
|
||||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) override;
|
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) override;
|
||||||
|
@ -45,6 +43,7 @@ namespace Kernel
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UDPSocket(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
UDPSocket(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
||||||
|
~UDPSocket();
|
||||||
|
|
||||||
struct PacketInfo
|
struct PacketInfo
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,8 +18,6 @@ namespace Kernel
|
||||||
static BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> create(SocketType, ino_t, const TmpInodeInfo&);
|
static BAN::ErrorOr<BAN::RefPtr<UnixDomainSocket>> create(SocketType, ino_t, const TmpInodeInfo&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void on_close_impl() override;
|
|
||||||
|
|
||||||
virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*) override;
|
virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*) override;
|
||||||
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
|
||||||
virtual BAN::ErrorOr<void> listen_impl(int) override;
|
virtual BAN::ErrorOr<void> listen_impl(int) override;
|
||||||
|
@ -33,7 +31,7 @@ namespace Kernel
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UnixDomainSocket(SocketType, ino_t, const TmpInodeInfo&);
|
UnixDomainSocket(SocketType, ino_t, const TmpInodeInfo&);
|
||||||
~UnixDomainSocket() { on_close_impl(); }
|
~UnixDomainSocket();
|
||||||
|
|
||||||
BAN::ErrorOr<void> add_packet(BAN::ConstByteSpan);
|
BAN::ErrorOr<void> add_packet(BAN::ConstByteSpan);
|
||||||
|
|
||||||
|
|
|
@ -56,12 +56,6 @@ namespace Kernel
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inode::on_close()
|
|
||||||
{
|
|
||||||
LockGuard _(m_mutex);
|
|
||||||
on_close_impl();
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name)
|
BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
LockGuard _(m_mutex);
|
||||||
|
|
|
@ -63,39 +63,6 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
ASSERT(!is_bound());
|
ASSERT(!is_bound());
|
||||||
ASSERT(m_process == nullptr);
|
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)
|
BAN::ErrorOr<void> TCPSocket::connect_impl(const sockaddr* address, socklen_t address_len)
|
||||||
|
@ -408,6 +375,38 @@ namespace Kernel
|
||||||
m_semaphore.unblock();
|
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()
|
void TCPSocket::set_connection_as_closed()
|
||||||
{
|
{
|
||||||
if (is_bound())
|
if (is_bound())
|
||||||
|
@ -427,13 +426,25 @@ namespace Kernel
|
||||||
static constexpr uint32_t retransmit_timeout_ms = 1000;
|
static constexpr uint32_t retransmit_timeout_ms = 1000;
|
||||||
|
|
||||||
BAN::RefPtr<TCPSocket> keep_alive = this;
|
BAN::RefPtr<TCPSocket> keep_alive = this;
|
||||||
|
bool started_close_sequence = false;
|
||||||
|
|
||||||
while (m_process)
|
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)
|
if (m_state == State::TimeWait && current_ms >= m_time_wait_start_ms + 30'000)
|
||||||
|
{
|
||||||
set_connection_as_closed();
|
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);
|
LockGuard _(m_mutex);
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Kernel
|
||||||
: NetworkSocket(network_layer, ino, inode_info)
|
: NetworkSocket(network_layer, ino, inode_info)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void UDPSocket::on_close_impl()
|
UDPSocket::~UDPSocket()
|
||||||
{
|
{
|
||||||
if (is_bound())
|
if (is_bound())
|
||||||
m_network_layer.unbind_socket(this, m_port);
|
m_network_layer.unbind_socket(this, m_port);
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnixDomainSocket::on_close_impl()
|
UnixDomainSocket::~UnixDomainSocket()
|
||||||
{
|
{
|
||||||
if (is_bound() && !is_bound_to_unused())
|
if (is_bound() && !is_bound_to_unused())
|
||||||
{
|
{
|
||||||
|
|
|
@ -317,8 +317,6 @@ namespace Kernel
|
||||||
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
|
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
|
||||||
((Pipe*)m_open_files[fd]->inode.ptr())->close_writing();
|
((Pipe*)m_open_files[fd]->inode.ptr())->close_writing();
|
||||||
|
|
||||||
m_open_files[fd]->inode->on_close();
|
|
||||||
|
|
||||||
m_open_files[fd].clear();
|
m_open_files[fd].clear();
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
Loading…
Reference in New Issue