libc: return EPIPE on send to shut down sockets

This intermediate fix still lacks the generation of SIGPIPE and return
of EINTR if the MSG_NOSIGNAL flag is not set in the call to send().
This commit is contained in:
Christian Helmuth 2019-11-12 09:04:50 +01:00
parent e70c04ef86
commit a54c04d247
1 changed files with 20 additions and 8 deletions

View File

@ -795,7 +795,6 @@ static ssize_t do_sendto(File_descriptor *fd,
if (!len) return Errno(EINVAL);
/* TODO ENOTCONN, EISCONN, EDESTADDRREQ */
/* TODO ECONNRESET */
try {
if (dest_addr && context->proto() == Context::Proto::UDP) {
@ -812,11 +811,26 @@ static ssize_t do_sendto(File_descriptor *fd,
lseek(context->data_fd(), 0, 0);
ssize_t out_len = write(context->data_fd(), buf, len);
if (out_len == 0) {
switch (context->proto()) {
case Socket_fs::Context::Proto::UDP: return Errno(ENETDOWN);
case Socket_fs::Context::Proto::TCP: return Errno(EAGAIN);
}
switch (context->proto()) {
case Socket_fs::Context::Proto::UDP:
if (out_len == 0) return Errno(ENETDOWN);
break;
case Socket_fs::Context::Proto::TCP:
if (out_len == 0) return Errno(EAGAIN);
/*
* Write errors to TCP-data files are reflected as EPIPE, which
* means the connection-mode socket is no longer connected. This
* explicitly does not differentiate ECONNRESET, which means the
* peer closed the connection while there was still unhandled data
* in the socket buffer on the remote side and sent an RST packet.
*
* TODO If the MSG_NOSIGNAL flag is not set, the SIGPIPE signal is
* generated to the calling thread.
*/
if (out_len == -1) return Errno(EPIPE);
break;
}
return out_len;
} catch (Socket_fs::Context::Inaccessible) {
@ -1016,8 +1030,6 @@ extern "C" int getifaddrs(struct ifaddrs **ifap)
static Lock lock;
Lock::Guard guard(lock);
// TODO: dual-stack / multi-homing
static sockaddr_in address;
static sockaddr_in netmask { 0 };
static sockaddr_in broadcast { 0 };