Kernel: Socket EPIPE and send SIGPIPE on write after hang up
This commit is contained in:
parent
e305698e6b
commit
943069b2a3
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -476,14 +476,25 @@ namespace Kernel
|
||||||
|
|
||||||
LockGuard _(inode->m_mutex);
|
LockGuard _(inode->m_mutex);
|
||||||
|
|
||||||
if (is_nonblock && !inode->can_write())
|
const auto check_errors =
|
||||||
return BAN::Error::from_errno(EWOULDBLOCK);
|
[&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())
|
||||||
|
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;
|
||||||
|
|
Loading…
Reference in New Issue