Kernel: Socket EPIPE and send SIGPIPE on write after hang up

This commit is contained in:
Bananymous 2025-06-03 10:24:44 +03:00
parent e305698e6b
commit 943069b2a3
2 changed files with 23 additions and 4 deletions

View File

@ -439,6 +439,8 @@ namespace Kernel
LockGuard _(m_mutex); LockGuard _(m_mutex);
const bool hungup_before = has_hungup_impl();
auto& header = buffer.as<const TCPHeader>(); auto& header = buffer.as<const TCPHeader>();
dprintln_if(DEBUG_TCP, "receiving {} {8b}", (uint8_t)m_state, header.flags); dprintln_if(DEBUG_TCP, "receiving {} {8b}", (uint8_t)m_state, header.flags);
dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.ack_number); dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.ack_number);
@ -609,6 +611,9 @@ namespace Kernel
} }
} }
if (!hungup_before && has_hungup_impl())
epoll_notify(EPOLLHUP);
m_thread_blocker.unblock(); m_thread_blocker.unblock();
} }
@ -690,9 +695,12 @@ namespace Kernel
auto target_address_len = m_connection_info->address_len; auto target_address_len = m_connection_info->address_len;
if (auto ret = m_network_layer.sendto(*this, {}, target_address, target_address_len); ret.is_error()) if (auto ret = m_network_layer.sendto(*this, {}, target_address, target_address_len); ret.is_error())
dwarnln("{}", ret.error()); dwarnln("{}", ret.error());
const bool hungup_before = has_hungup_impl();
m_state = m_next_state; m_state = m_next_state;
if (m_state == State::Established) if (m_state == State::Established)
m_has_connected = true; m_has_connected = true;
if (!hungup_before && has_hungup_impl())
epoll_notify(EPOLLHUP);
continue; continue;
} }

View File

@ -476,14 +476,25 @@ namespace Kernel
LockGuard _(inode->m_mutex); LockGuard _(inode->m_mutex);
const auto check_errors =
[&inode, is_nonblock]() -> BAN::ErrorOr<void>
{
if (inode->has_hungup())
{
Thread::current().add_signal(SIGPIPE);
return BAN::Error::from_errno(EPIPE);
}
if (is_nonblock && !inode->can_write()) if (is_nonblock && !inode->can_write())
return BAN::Error::from_errno(EWOULDBLOCK); return BAN::Error::from_errno(EWOULDBLOCK);
return {};
};
TRY(check_errors());
size_t total_sent = 0; size_t total_sent = 0;
while (total_sent < buffer.size()) while (total_sent < buffer.size())
{ {
if (is_nonblock && !inode->can_write()) TRY(check_errors());
return total_sent;
const size_t nsend = TRY(inode->sendto(buffer.slice(total_sent), address, address_len)); const size_t nsend = TRY(inode->sendto(buffer.slice(total_sent), address, address_len));
if (nsend == 0) if (nsend == 0)
return 0; return 0;