Jelajahi Sumber

Kernel: Add support for MSG_NOSIGNAL and properly send SIGPIPE

Previously we didn't send the SIGPIPE signal to processes when
sendto()/sendmsg()/etc. returned EPIPE. And now we do.

This also adds support for MSG_NOSIGNAL to suppress the signal.
Gunnar Beutner 2 tahun lalu
induk
melakukan
ce4b66e908

+ 1 - 0
Kernel/API/POSIX/sys/socket.h

@@ -60,6 +60,7 @@ extern "C" {
 #define MSG_DONTROUTE 0x10
 #define MSG_WAITALL 0x20
 #define MSG_DONTWAIT 0x40
+#define MSG_NOSIGNAL 0x80
 
 typedef uint16_t sa_family_t;
 

+ 1 - 3
Kernel/FileSystem/FIFO.cpp

@@ -120,10 +120,8 @@ ErrorOr<size_t> FIFO::read(OpenFileDescription& fd, u64, UserOrKernelBuffer& buf
 
 ErrorOr<size_t> FIFO::write(OpenFileDescription& fd, u64, UserOrKernelBuffer const& buffer, size_t size)
 {
-    if (!m_readers) {
-        Thread::current()->send_signal(SIGPIPE, &Process::current());
+    if (!m_readers)
         return EPIPE;
-    }
     if (!fd.is_blocking() && m_buffer->space_for_writing() == 0)
         return EAGAIN;
 

+ 12 - 2
Kernel/Syscalls/socket.cpp

@@ -194,8 +194,11 @@ ErrorOr<FlatPtr> Process::sys$sendmsg(int sockfd, Userspace<const struct msghdr*
         return ENOTSOCK;
 
     auto& socket = *description->socket();
-    if (socket.is_shut_down_for_writing())
+    if (socket.is_shut_down_for_writing()) {
+        if ((flags & MSG_NOSIGNAL) == 0)
+            Thread::current()->send_signal(SIGPIPE, &Process::current());
         return EPIPE;
+    }
     auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len));
 
     while (true) {
@@ -211,7 +214,14 @@ ErrorOr<FlatPtr> Process::sys$sendmsg(int sockfd, Userspace<const struct msghdr*
             // TODO: handle exceptions in unblock_flags
         }
 
-        auto bytes_sent = TRY(socket.sendto(*description, data_buffer, iovs[0].iov_len, flags, user_addr, addr_length));
+        auto bytes_sent_or_error = socket.sendto(*description, data_buffer, iovs[0].iov_len, flags, user_addr, addr_length);
+        if (bytes_sent_or_error.is_error()) {
+            if ((flags & MSG_NOSIGNAL) == 0 && bytes_sent_or_error.error().code() == EPIPE)
+                Thread::current()->send_signal(SIGPIPE, &Process::current());
+            return bytes_sent_or_error.release_error();
+        }
+
+        auto bytes_sent = bytes_sent_or_error.release_value();
         if (bytes_sent > 0)
             return bytes_sent;
     }

+ 2 - 0
Kernel/Syscalls/write.cpp

@@ -78,6 +78,8 @@ ErrorOr<FlatPtr> Process::do_write(OpenFileDescription& description, UserOrKerne
                 return total_nwritten;
             if (nwritten_or_error.error().code() == EAGAIN)
                 continue;
+            if (nwritten_or_error.error().code() == EPIPE)
+                Thread::current()->send_signal(SIGPIPE, &Process::current());
             return nwritten_or_error.release_error();
         }
         VERIFY(nwritten_or_error.value() > 0);