From 24fd8fb16f0779d2bfd172192b0d24c25444fad4 Mon Sep 17 00:00:00 2001 From: sin-ack Date: Mon, 7 Feb 2022 11:03:34 +0000 Subject: [PATCH] Kernel: Ensure socket is suitable for writing in sys$sendmsg Previously we would return a bytes written value of 0 if the writing end of the socket was full. Now we either exit with EAGAIN if the socket description is non-blocking, or block until the description can be written to. This is mostly a copy of the conditions in sys$write but with the "total nwritten" parts removed as sys$sendmsg does not have that. --- Kernel/Syscalls/socket.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Kernel/Syscalls/socket.cpp b/Kernel/Syscalls/socket.cpp index a8f15e02ab..b522513d48 100644 --- a/Kernel/Syscalls/socket.cpp +++ b/Kernel/Syscalls/socket.cpp @@ -196,12 +196,29 @@ ErrorOr Process::sys$sendmsg(int sockfd, Userspaceis_socket()) return ENOTSOCK; + auto& socket = *description->socket(); if (socket.is_shut_down_for_writing()) return EPIPE; auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len)); - auto bytes_sent = TRY(socket.sendto(*description, data_buffer, iovs[0].iov_len, flags, user_addr, addr_length)); - return bytes_sent; + + while (true) { + while (!description->can_write()) { + if (!description->is_blocking()) { + return EAGAIN; + } + + auto unblock_flags = Thread::FileBlocker::BlockFlags::None; + if (Thread::current()->block({}, *description, unblock_flags).was_interrupted()) { + return EINTR; + } + // TODO: handle exceptions in unblock_flags + } + + auto bytes_sent = TRY(socket.sendto(*description, data_buffer, iovs[0].iov_len, flags, user_addr, addr_length)); + if (bytes_sent > 0) + return bytes_sent; + } } ErrorOr Process::sys$recvmsg(int sockfd, Userspace user_msg, int flags)