From 446220494e8b7dcb6c4553e97df036733ddd19fd Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 2 Jun 2024 16:48:55 +0300 Subject: [PATCH] Kernel: Unix domain sockets close can now be detected When a unix domain socket is closed and it has a connection to another socket, it will make the other socket readable and recv will return 0. This allows detection of socket closing --- kernel/include/kernel/Networking/UNIX/Socket.h | 1 + kernel/kernel/Networking/UNIX/Socket.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/kernel/include/kernel/Networking/UNIX/Socket.h b/kernel/include/kernel/Networking/UNIX/Socket.h index 4e46bd84..e8898201 100644 --- a/kernel/include/kernel/Networking/UNIX/Socket.h +++ b/kernel/include/kernel/Networking/UNIX/Socket.h @@ -46,6 +46,7 @@ namespace Kernel { bool listening { false }; BAN::Atomic connection_done { false }; + mutable BAN::Atomic target_closed { false }; BAN::WeakPtr connection; BAN::Queue> pending_connections; Semaphore pending_semaphore; diff --git a/kernel/kernel/Networking/UNIX/Socket.cpp b/kernel/kernel/Networking/UNIX/Socket.cpp index 16a0e8ce..7232f608 100644 --- a/kernel/kernel/Networking/UNIX/Socket.cpp +++ b/kernel/kernel/Networking/UNIX/Socket.cpp @@ -55,7 +55,15 @@ namespace Kernel auto it = s_bound_sockets.find(m_bound_path); if (it != s_bound_sockets.end()) s_bound_sockets.remove(it); + m_bound_path.clear(); } + if (m_info.has()) + { + auto& connection_info = m_info.get(); + if (auto connection = connection_info.connection.lock(); connection && connection->m_info.has()) + connection->m_info.get().target_closed = true; + } + m_info.clear(); } BAN::ErrorOr UnixDomainSocket::accept_impl(sockaddr* address, socklen_t* address_len) @@ -256,6 +264,8 @@ namespace Kernel if (m_info.has()) { auto& connection_info = m_info.get(); + if (connection_info.target_closed) + return true; if (!connection_info.pending_connections.empty()) return true; if (!connection_info.connection) @@ -338,6 +348,8 @@ namespace Kernel if (m_info.has()) { auto& connection_info = m_info.get(); + if (connection_info.target_closed.compare_exchange(true, false)) + return 0; if (!connection_info.connection) return BAN::Error::from_errno(ENOTCONN); }