diff --git a/libc/intrin/describeflags.h b/libc/intrin/describeflags.h
index 917ef0f46..85814c78d 100644
--- a/libc/intrin/describeflags.h
+++ b/libc/intrin/describeflags.h
@@ -8,8 +8,8 @@ struct thatispacked DescribeFlags {
   const char *name;
 };
 
-const char *_DescribeFlags(char *, size_t, const struct DescribeFlags *,
-                           size_t, const char *, unsigned) libcesque;
+const char *_DescribeFlags(char *, size_t, const struct DescribeFlags *, size_t,
+                           const char *, unsigned) libcesque;
 
 const char *_DescribeArchPrctlCode(char[12], int) libcesque;
 const char *_DescribeCancelState(char[12], int, int *) libcesque;
@@ -27,6 +27,7 @@ const char *_DescribeItimer(char[12], int) libcesque;
 const char *_DescribeMapFlags(char[64], int) libcesque;
 const char *_DescribeMapping(char[8], int, int) libcesque;
 const char *_DescribeMremapFlags(char[30], int) libcesque;
+const char *_DescribeMsg(char[16], int) libcesque;
 const char *_DescribeMsyncFlags(char[48], int) libcesque;
 const char *_DescribeNtConsoleInFlags(char[256], uint32_t) libcesque;
 const char *_DescribeNtConsoleOutFlags(char[128], uint32_t) libcesque;
@@ -84,6 +85,7 @@ const char *_DescribeWhichPrio(char[12], int) libcesque;
 #define DescribeMapFlags(x)          _DescribeMapFlags(alloca(64), x)
 #define DescribeMapping(x, y)        _DescribeMapping(alloca(8), x, y)
 #define DescribeMremapFlags(x)       _DescribeMremapFlags(alloca(30), x)
+#define DescribeMsg(x)               _DescribeMsg(alloca(16), x)
 #define DescribeMsyncFlags(x)        _DescribeMsyncFlags(alloca(48), x)
 #define DescribeNtConsoleInFlags(x)  _DescribeNtConsoleInFlags(alloca(256), x)
 #define DescribeNtConsoleOutFlags(x) _DescribeNtConsoleOutFlags(alloca(128), x)
diff --git a/libc/intrin/describemsg.c b/libc/intrin/describemsg.c
new file mode 100644
index 000000000..9cfc5372e
--- /dev/null
+++ b/libc/intrin/describemsg.c
@@ -0,0 +1,36 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2024 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/intrin/describeflags.h"
+#include "libc/macros.h"
+#include "libc/sysv/consts/msg.h"
+
+const char *_DescribeMsg(char buf[16], int x) {
+  const struct DescribeFlags kMsgFlags[] = {
+      {MSG_FASTOPEN, "FASTOPEN"},    // order matters
+      {MSG_OOB, "OOB"},              //
+      {MSG_PEEK, "PEEK"},            //
+      {MSG_DONTROUTE, "DONTROUTE"},  //
+      {MSG_DONTWAIT, "DONTWAIT"},    //
+      {MSG_WAITALL, "WAITALL"},      //
+      {MSG_NOSIGNAL, "NOSIGNAL"},    //
+      {MSG_TRUNC, "TRUNC"},          //
+      {MSG_CTRUNC, "CTRUNC"},        //
+  };
+  return _DescribeFlags(buf, 16, kMsgFlags, ARRAYLEN(kMsgFlags), "MSG_", x);
+}
diff --git a/libc/sock/internal.h b/libc/sock/internal.h
index b8704360b..9dbd690dc 100644
--- a/libc/sock/internal.h
+++ b/libc/sock/internal.h
@@ -65,7 +65,7 @@ int sys_select_nt(int, fd_set *, fd_set *, fd_set *, struct timeval *,
 
 size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *, size_t);
 
-ssize_t __winsock_block(int64_t, uint32_t, int, uint32_t, uint64_t,
+ssize_t __winsock_block(int64_t, uint32_t, bool, uint32_t, uint64_t,
                         int (*)(int64_t, struct NtOverlapped *, uint32_t *,
                                 void *),
                         void *);
diff --git a/libc/sock/recv-nt.c b/libc/sock/recv-nt.c
index 14b0e0edd..013fc930a 100644
--- a/libc/sock/recv-nt.c
+++ b/libc/sock/recv-nt.c
@@ -17,15 +17,17 @@
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
 #include "libc/calls/internal.h"
-#include "libc/calls/struct/iovec.h"
 #include "libc/calls/struct/sigset.internal.h"
-#include "libc/intrin/fds.h"
 #include "libc/nt/struct/iovec.h"
+#include "libc/nt/struct/overlapped.h"
+#include "libc/nt/thunk/msabi.h"
 #include "libc/nt/winsock.h"
 #include "libc/sock/internal.h"
 #include "libc/sock/syscall_fd.internal.h"
+#include "libc/sysv/consts/fio.h"
 #include "libc/sysv/consts/o.h"
 #include "libc/sysv/errfuns.h"
+#include "libc/vga/vga.internal.h"
 #ifdef __x86_64__
 
 #define _MSG_OOB      1
@@ -33,6 +35,8 @@
 #define _MSG_WAITALL  8
 #define _MSG_DONTWAIT 64
 
+__msabi extern typeof(__sys_ioctlsocket_nt) *const __imp_ioctlsocket;
+
 struct RecvArgs {
   const struct iovec *iov;
   size_t iovlen;
@@ -54,13 +58,24 @@ textwindows ssize_t sys_recv_nt(int fd, const struct iovec *iov, size_t iovlen,
     return einval();
   ssize_t rc;
   struct Fd *f = g_fds.p + fd;
-  sigset_t m = __sig_block();
-  bool nonblock = !(flags & _MSG_WAITALL) &&
-                  ((f->flags & O_NONBLOCK) || (flags & _MSG_DONTWAIT));
-  flags &= ~_MSG_DONTWAIT;
-  rc = __winsock_block(f->handle, flags, nonblock, f->rcvtimeo, m,
-                       sys_recv_nt_start, &(struct RecvArgs){iov, iovlen});
-  __sig_unblock(m);
+  sigset_t waitmask = __sig_block();
+
+  // "Be aware that if the underlying transport provider does not
+  //  support MSG_WAITALL, or if the socket is in a non-blocking mode,
+  //  then this call will fail with WSAEOPNOTSUPP. Also, if MSG_WAITALL
+  //  is specified along with MSG_OOB, MSG_PEEK, or MSG_PARTIAL, then
+  //  this call will fail with WSAEOPNOTSUPP."
+  //                             —Quoth MSDN § WSARecv
+  if (flags & _MSG_WAITALL)
+    __imp_ioctlsocket(f->handle, FIONBIO, (uint32_t[]){0});
+
+  rc = __winsock_block(f->handle, flags & ~_MSG_DONTWAIT,
+                       (f->flags & O_NONBLOCK) || (flags & _MSG_DONTWAIT),
+                       f->rcvtimeo, waitmask, sys_recv_nt_start,
+                       &(struct RecvArgs){iov, iovlen});
+
+  __sig_unblock(waitmask);
+
   return rc;
 }
 
diff --git a/libc/sock/recv.c b/libc/sock/recv.c
index 8d97329b3..31003e7fb 100644
--- a/libc/sock/recv.c
+++ b/libc/sock/recv.c
@@ -20,20 +20,40 @@
 #include "libc/calls/internal.h"
 #include "libc/calls/struct/iovec.internal.h"
 #include "libc/dce.h"
+#include "libc/intrin/describeflags.h"
 #include "libc/intrin/strace.h"
 #include "libc/sock/internal.h"
 #include "libc/sock/sock.h"
 #include "libc/sock/syscall_fd.internal.h"
+#include "libc/sysv/consts/msg.h"
 #include "libc/sysv/errfuns.h"
 
 /**
  * Receives data from network socket.
  *
+ * Calling `recv(fd, p, n, 0)` is equivalent to `read(fd, p, n)`.
+ *
+ * Unlike files where the OS tries very hard to fulfill the entire
+ * requested `size` before returning, read operations on sockets aim to
+ * return as quickly as possible. For example, if 10 bytes are requested
+ * and a packet comes in with only 5 bytes, then recv() will most likely
+ * return those 5 bytes before waiting longer. The `MSG_WAITALL` flag
+ * may be passed when waiting longer is desired. In that case, short
+ * reads should only be possible when the connection status changes or
+ * the receive operation is interrupted by a signal.
+ *
  * @param fd is the file descriptor returned by socket()
  * @param buf is where received network data gets copied
  * @param size is the byte capacity of buf
  * @param flags can have `MSG_OOB`, `MSG_PEEK`, `MSG_DONTWAIT`, `MSG_WAITALL`
  * @return number of bytes received, 0 on remote close, or -1 w/ errno
+ * @raise EINTR if signal handler was called instead
+ * @raise EINVAL if unknown bits were passed in `flags`
+ * @raise EINVAL if flag isn't supported by host operating system
+ * @raise EINVAL if `MSG_WAITALL` and `MSG_PEEK` were both passed
+ * @raise EBADF if `fd` is an invalid file descriptor
+ * @raise EAGAIN if `MSG_DONTWAIT` was passed and no data was available
+ * @raise EAGAIN if `O_NONBLOCK` is in play and no data was available
  * @error EINTR, EHOSTUNREACH, ECONNRESET (UDP ICMP Port Unreachable),
  *     EPIPE (if MSG_NOSIGNAL), EMSGSIZE, ENOTSOCK, EFAULT, etc.
  * @cancelationpoint
@@ -44,7 +64,11 @@ ssize_t recv(int fd, void *buf, size_t size, int flags) {
   ssize_t rc;
   BEGIN_CANCELATION_POINT;
 
-  if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
+  if ((flags & (MSG_WAITALL | MSG_PEEK)) == (MSG_WAITALL | MSG_PEEK)) {
+    // this is possible on some OSes like Linux but it breaks FreeBSD
+    // and Windows will raise EOPNOTSUPP when it gets passed together
+    return einval();
+  } else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
     rc = enotsock();
   } else if (!IsWindows()) {
     rc = sys_recvfrom(fd, buf, size, flags, 0, 0);
@@ -65,7 +89,8 @@ ssize_t recv(int fd, void *buf, size_t size, int flags) {
   }
 
   END_CANCELATION_POINT;
-  DATATRACE("recv(%d, [%#.*hhs%s], %'zu, %#x) → %'ld% lm", fd,
-            MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, flags, rc);
+  DATATRACE("recv(%d, [%#.*hhs%s], %'zu, %s) → %'ld% lm", fd,
+            MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size,
+            DescribeMsg(flags), rc);
   return rc;
 }
diff --git a/libc/sock/recvfrom-nt.c b/libc/sock/recvfrom-nt.c
index c94c94260..e40e6ed6a 100644
--- a/libc/sock/recvfrom-nt.c
+++ b/libc/sock/recvfrom-nt.c
@@ -59,14 +59,13 @@ textwindows ssize_t sys_recvfrom_nt(int fd, const struct iovec *iov,
     return einval();
   ssize_t rc;
   struct Fd *f = g_fds.p + fd;
-  sigset_t m = __sig_block();
-  bool nonblock = (f->flags & O_NONBLOCK) || (flags & _MSG_DONTWAIT);
-  flags &= ~_MSG_DONTWAIT;
-  rc = __winsock_block(f->handle, flags, nonblock, f->rcvtimeo, m,
-                       sys_recvfrom_nt_start,
+  sigset_t waitmask = __sig_block();
+  rc = __winsock_block(f->handle, flags & ~_MSG_DONTWAIT,
+                       (f->flags & O_NONBLOCK) || (flags & _MSG_DONTWAIT),
+                       f->rcvtimeo, waitmask, sys_recvfrom_nt_start,
                        &(struct RecvFromArgs){iov, iovlen, opt_out_srcaddr,
                                               opt_inout_srcaddrsize});
-  __sig_unblock(m);
+  __sig_unblock(waitmask);
   return rc;
 }
 
diff --git a/libc/sock/recvfrom.c b/libc/sock/recvfrom.c
index d323b775c..dbcda5b2c 100644
--- a/libc/sock/recvfrom.c
+++ b/libc/sock/recvfrom.c
@@ -21,6 +21,7 @@
 #include "libc/calls/struct/iovec.h"
 #include "libc/calls/struct/iovec.internal.h"
 #include "libc/dce.h"
+#include "libc/intrin/describeflags.h"
 #include "libc/intrin/strace.h"
 #include "libc/nt/winsock.h"
 #include "libc/sock/internal.h"
@@ -95,7 +96,11 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags,
   }
 
   END_CANCELATION_POINT;
-  DATATRACE("recvfrom(%d, [%#.*hhs%s], %'zu, %#x) → %'ld% lm", fd,
-            MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, flags, rc);
+  DATATRACE(
+      "recvfrom(%d, [%#.*hhs%s], %'zu, %s, %s) → %'ld% lm", fd,
+      MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, DescribeMsg(flags),
+      DescribeSockaddr(opt_out_srcaddr,
+                       opt_inout_srcaddrsize ? *opt_inout_srcaddrsize : 0),
+      rc);
   return rc;
 }
diff --git a/libc/sock/send-nt.c b/libc/sock/send-nt.c
index b12c0f2b4..c9169003c 100644
--- a/libc/sock/send-nt.c
+++ b/libc/sock/send-nt.c
@@ -17,20 +17,25 @@
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
 #include "libc/calls/internal.h"
-#include "libc/calls/struct/iovec.h"
+#include "libc/calls/sig.internal.h"
+#include "libc/calls/struct/iovec.internal.h"
 #include "libc/calls/struct/sigset.internal.h"
-#include "libc/intrin/fds.h"
+#include "libc/errno.h"
+#include "libc/nt/errors.h"
 #include "libc/nt/struct/iovec.h"
+#include "libc/nt/struct/overlapped.h"
 #include "libc/nt/winsock.h"
 #include "libc/sock/internal.h"
-#include "libc/sock/syscall_fd.internal.h"
-#include "libc/sysv/consts/o.h"
+#include "libc/sysv/consts/sicode.h"
+#include "libc/sysv/consts/sig.h"
 #include "libc/sysv/errfuns.h"
+#include "libc/vga/vga.internal.h"
 #ifdef __x86_64__
 
 #define _MSG_OOB       1
 #define _MSG_DONTROUTE 4
 #define _MSG_DONTWAIT  64
+#define _MSG_NOSIGNAL  0x10000000
 
 struct SendArgs {
   const struct iovec *iov;
@@ -49,23 +54,24 @@ textwindows static int sys_send_nt_start(int64_t handle,
 
 textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
                                 uint32_t flags) {
-  if (flags & ~(_MSG_DONTWAIT | _MSG_OOB | _MSG_DONTROUTE))
+  if (flags & ~(_MSG_DONTWAIT | _MSG_OOB | _MSG_DONTROUTE | _MSG_NOSIGNAL))
     return einval();
   ssize_t rc;
   struct Fd *f = g_fds.p + fd;
-  sigset_t m = __sig_block();
+  sigset_t waitmask = __sig_block();
 
-  // we don't check O_NONBLOCK because we want to avoid needing to call
-  // WSAPoll() every time we write() to a non-blocking socket. WIN32 is
-  // unsafe at canceling socket sends. lots of code doesn't check write
-  // return status. good programs that sincerely want to avoid blocking
-  // on send() operations should have already called poll() beforehand.
-  bool nonblock = flags & _MSG_DONTWAIT;
+  rc = __winsock_block(f->handle, flags & ~(_MSG_DONTWAIT | _MSG_NOSIGNAL),
+                       false, f->sndtimeo, waitmask, sys_send_nt_start,
+                       &(struct SendArgs){iov, iovlen});
+
+  __sig_unblock(waitmask);
+
+  if (rc == -1 && errno == WSAESHUTDOWN) {  // ESHUTDOWN
+    errno = kNtErrorBrokenPipe;             // EPIPE
+    if (!(flags & _MSG_NOSIGNAL))
+      __sig_raise(SIGPIPE, SI_KERNEL);
+  }
 
-  flags &= ~_MSG_DONTWAIT;
-  rc = __winsock_block(f->handle, flags, -nonblock, f->sndtimeo, m,
-                       sys_send_nt_start, &(struct SendArgs){iov, iovlen});
-  __sig_unblock(m);
   return rc;
 }
 
diff --git a/libc/sock/send.c b/libc/sock/send.c
index 25c836ddc..81831b27c 100644
--- a/libc/sock/send.c
+++ b/libc/sock/send.c
@@ -21,6 +21,7 @@
 #include "libc/calls/struct/iovec.h"
 #include "libc/calls/struct/iovec.internal.h"
 #include "libc/dce.h"
+#include "libc/intrin/describeflags.h"
 #include "libc/intrin/strace.h"
 #include "libc/macros.h"
 #include "libc/sock/internal.h"
@@ -78,7 +79,7 @@ ssize_t send(int fd, const void *buf, size_t size, int flags) {
   }
 
   END_CANCELATION_POINT;
-  DATATRACE("send(%d, %#.*hhs%s, %'zu, %#x) → %'ld% lm", fd,
-            MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, flags, rc);
+  DATATRACE("send(%d, %#.*hhs%s, %'zu, %s) → %'ld% lm", fd, MAX(0, MIN(40, rc)),
+            buf, rc > 40 ? "..." : "", size, DescribeMsg(flags), rc);
   return rc;
 }
diff --git a/libc/sock/sendto-nt.c b/libc/sock/sendto-nt.c
index 41e3520ba..831cf6552 100644
--- a/libc/sock/sendto-nt.c
+++ b/libc/sock/sendto-nt.c
@@ -17,20 +17,26 @@
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
 #include "libc/calls/internal.h"
+#include "libc/calls/sig.internal.h"
 #include "libc/calls/struct/iovec.h"
 #include "libc/calls/struct/sigset.internal.h"
+#include "libc/errno.h"
 #include "libc/intrin/fds.h"
+#include "libc/nt/errors.h"
 #include "libc/nt/struct/iovec.h"
 #include "libc/nt/winsock.h"
 #include "libc/sock/internal.h"
 #include "libc/sock/syscall_fd.internal.h"
 #include "libc/sysv/consts/o.h"
+#include "libc/sysv/consts/sicode.h"
+#include "libc/sysv/consts/sig.h"
 #include "libc/sysv/errfuns.h"
 #ifdef __x86_64__
 
 #define _MSG_OOB       1
 #define _MSG_DONTROUTE 4
 #define _MSG_DONTWAIT  64
+#define _MSG_NOSIGNAL  0x10000000
 
 struct SendToArgs {
   const struct iovec *iov;
@@ -52,17 +58,25 @@ static textwindows int sys_sendto_nt_start(int64_t handle,
 textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
                                   size_t iovlen, uint32_t flags,
                                   void *opt_in_addr, uint32_t in_addrsize) {
-  if (flags & ~(_MSG_DONTWAIT | _MSG_OOB | _MSG_DONTROUTE))
+  if (flags & ~(_MSG_DONTWAIT | _MSG_OOB | _MSG_DONTROUTE | _MSG_NOSIGNAL))
     return einval();
   ssize_t rc;
   struct Fd *f = g_fds.p + fd;
-  sigset_t m = __sig_block();
-  bool nonblock = (f->flags & O_NONBLOCK) || (flags & _MSG_DONTWAIT);
-  flags &= ~_MSG_DONTWAIT;
-  rc = __winsock_block(
-      f->handle, flags, -nonblock, f->sndtimeo, m, sys_sendto_nt_start,
-      &(struct SendToArgs){iov, iovlen, opt_in_addr, in_addrsize});
-  __sig_unblock(m);
+  sigset_t waitmask = __sig_block();
+
+  rc = __winsock_block(f->handle, flags & ~(_MSG_DONTWAIT | _MSG_NOSIGNAL),
+                       false, f->sndtimeo, waitmask, sys_sendto_nt_start,
+                       &(struct SendToArgs){iov, iovlen,  //
+                                            opt_in_addr, in_addrsize});
+
+  __sig_unblock(waitmask);
+
+  if (rc == -1 && errno == WSAESHUTDOWN) {  // ESHUTDOWN
+    errno = kNtErrorBrokenPipe;             // EPIPE
+    if (!(flags & _MSG_NOSIGNAL))
+      __sig_raise(SIGPIPE, SI_KERNEL);
+  }
+
   return rc;
 }
 
diff --git a/libc/sock/sendto.c b/libc/sock/sendto.c
index a949c711d..f5a458aeb 100644
--- a/libc/sock/sendto.c
+++ b/libc/sock/sendto.c
@@ -22,6 +22,7 @@
 #include "libc/calls/struct/iovec.h"
 #include "libc/calls/struct/iovec.internal.h"
 #include "libc/dce.h"
+#include "libc/intrin/describeflags.h"
 #include "libc/intrin/strace.h"
 #include "libc/macros.h"
 #include "libc/sock/internal.h"
@@ -88,8 +89,8 @@ ssize_t sendto(int fd, const void *buf, size_t size, int flags,
   }
 
   END_CANCELATION_POINT;
-  DATATRACE("sendto(%d, %#.*hhs%s, %'zu, %#x, %p, %u) → %'ld% lm", fd,
-            MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, flags,
-            opt_addr, addrsize, rc);
+  DATATRACE("sendto(%d, %#.*hhs%s, %'zu, %s, %s) → %'ld% lm", fd,
+            MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size,
+            DescribeMsg(flags), DescribeSockaddr(opt_addr, addrsize), rc);
   return rc;
 }
diff --git a/libc/sock/winsockblock.c b/libc/sock/winsockblock.c
index 6eb1e702e..32a7e0c82 100644
--- a/libc/sock/winsockblock.c
+++ b/libc/sock/winsockblock.c
@@ -42,7 +42,7 @@
 #ifdef __x86_64__
 
 textwindows ssize_t
-__winsock_block(int64_t handle, uint32_t flags, int nonblock,
+__winsock_block(int64_t handle, uint32_t flags, bool nonblock,
                 uint32_t srwtimeout, sigset_t waitmask,
                 int StartSocketOp(int64_t handle, struct NtOverlapped *overlap,
                                   uint32_t *flags, void *arg),
@@ -63,21 +63,6 @@ __winsock_block(int64_t handle, uint32_t flags, int nonblock,
     bool got_eagain = false;
     uint32_t other_error = 0;
 
-    // send() and sendto() provide O_NONBLOCK as a negative number
-    // because winsock has a bug that causes CancelIoEx() to cause
-    // WSAGetOverlappedResult() to report errors when it succeeded
-    if (nonblock < 0) {
-      struct sys_pollfd_nt fds[1] = {{handle, POLLOUT}};
-      switch (WSAPoll(fds, 1, 0)) {
-        case -1:
-          return __winsockerr();
-        case 0:
-          return eagain();
-        default:
-          break;
-      }
-    }
-
     // create event handle for overlapped i/o
     intptr_t event;
     if (!(event = WSACreateEvent()))
@@ -86,7 +71,10 @@ __winsock_block(int64_t handle, uint32_t flags, int nonblock,
     struct NtOverlapped overlap = {.hEvent = event};
     bool32 ok = !StartSocketOp(handle, &overlap, &flags, arg);
     if (!ok && WSAGetLastError() == kNtErrorIoPending) {
-      if (nonblock > 0) {
+      if (nonblock) {
+        // send() and sendto() shall not pass O_NONBLOCK along to here
+        // because winsock has a bug that causes CancelIoEx() to cause
+        // WSAGetOverlappedResult() to report errors when it succeeded
         CancelIoEx(handle, &overlap);
         got_eagain = true;
       } else {
diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh
index a372572b5..63e532bb7 100755
--- a/libc/sysv/consts.sh
+++ b/libc/sysv/consts.sh
@@ -1138,32 +1138,12 @@ syscon	reboot	RB_NOSYNC				0x20000000		0x20000000		4			4			4			4			4			0x2000000
 syscon	msg	MSG_OOB					1			1			1			1			1			1			1			1			# consensus
 syscon	msg	MSG_PEEK				2			2			2			2			2			2			2			2			# consensus
 syscon	msg	MSG_DONTROUTE				4			4			4			4			4			4			4			4			# consensus
-syscon	msg	MSG_FASTOPEN				0x20000000		0x20000000		0			0			0			0			0			0			# TODO
-syscon	msg	MSG_WAITALL				0x0100			0x0100			0x40			0x40			0x40			0x40			0x40			8			# bsd consensus
-syscon	msg	MSG_MORE				0x8000			0x8000			0			0			0			0			0			0			# send/sendto: manual TCP_CORK hbasically
-syscon	msg	MSG_NOSIGNAL				0x4000			0x4000			0x80000			0x80000			0x020000		0x0400			0x0400			0			# send/sendto: don't SIGPIPE on EOF
 syscon	msg	MSG_DONTWAIT				0x40			0x40			0x80			0x80			0x80			0x80			0x80			0x40			# send/sendto: manual non-blocking
+syscon	msg	MSG_WAITALL				0x0100			0x0100			0x40			0x40			0x40			0x40			0x40			8			# bsd consensus
+syscon	msg	MSG_NOSIGNAL				0x4000			0x4000			0x80000			0x80000			0x020000		0x0400			0x0400			0x10000000		# send/sendto: don't raise sigpipe on local shutdown
 syscon	msg	MSG_TRUNC				0x20			0x20			0x10			0x10			0x10			0x10			0x10			0x0100			# bsd consensus
 syscon	msg	MSG_CTRUNC				8			8			0x20			0x20			0x20			0x20			0x20			0x0200			# bsd consensus
-syscon	msg	MSG_ERRQUEUE				0x2000			0x2000			0			0			0			0			0			0x1000			# bsd consensus
-syscon	msg	MSG_NOERROR				0x1000			0x1000			0x1000			0x1000			0x1000			0x1000			0x1000			0			# unix consensus
-syscon	msg	MSG_EOR					0x80			0x80			8			8			8			8			8			0			# bsd consensus
-syscon	msg	MSG_CMSG_CLOEXEC			0x40000000		0x40000000		0			0			0x040000		0x0800			0x0800			0
-syscon	msg	MSG_WAITFORONE				0x010000		0x010000		0			0			0x080000		0			0x2000			0
-syscon	msg	MSG_BATCH				0x040000		0x040000		0			0			0			0			0			0
-syscon	msg	MSG_CONFIRM				0x0800			0x0800			0			0			0			0			0			0
-syscon	msg	MSG_EXCEPT				0x2000			0x2000			0			0			0			0			0			0
-syscon	msg	MSG_FIN					0x0200			0x0200			0x0100			0x0100			0x0100			0			0			0
-syscon	msg	MSG_EOF					0x0200			0x0200			0x0100			0x0100			0x0100			0			0			0
-syscon	msg	MSG_INFO				12			12			0			0			0			0			0			0
-syscon	msg	MSG_PARITY_ERROR			9			9			0			0			0			0			0			0
-syscon	msg	MSG_PROXY				0x10			0x10			0			0			0			0			0			0
-syscon	msg	MSG_RST					0x1000			0x1000			0			0			0			0			0			0
-syscon	msg	MSG_STAT				11			11			0			0			0			0			0			0
-syscon	msg	MSG_SYN					0x0400			0x0400			0			0			0			0			0			0
-syscon	msg	MSG_BCAST				0			0			0			0			0			0x100			0x100			0
-syscon	msg	MSG_MCAST				0			0			0			0			0			0x200			0x200			0
-syscon	msg	MSG_NOTIFICATION			0x8000			0x8000			0			0			0x2000			0			0x4000			0
+syscon	msg	MSG_FASTOPEN				0x20000000		0x20000000		-1			-1			-1			-1			-1			-1			#
 
 #	getpriority() / setpriority() magnums (a.k.a. nice)
 #
diff --git a/libc/sysv/consts/MSG_BATCH.S b/libc/sysv/consts/MSG_BATCH.S
deleted file mode 100644
index e171f4f2f..000000000
--- a/libc/sysv/consts/MSG_BATCH.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_BATCH,0x040000,0x040000,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_BCAST.S b/libc/sysv/consts/MSG_BCAST.S
deleted file mode 100644
index 082634257..000000000
--- a/libc/sysv/consts/MSG_BCAST.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_BCAST,0,0,0,0,0,0x100,0x100,0
diff --git a/libc/sysv/consts/MSG_CMSG_CLOEXEC.S b/libc/sysv/consts/MSG_CMSG_CLOEXEC.S
deleted file mode 100644
index ea66034e3..000000000
--- a/libc/sysv/consts/MSG_CMSG_CLOEXEC.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_CMSG_CLOEXEC,0x40000000,0x40000000,0,0,0x040000,0x0800,0x0800,0
diff --git a/libc/sysv/consts/MSG_CONFIRM.S b/libc/sysv/consts/MSG_CONFIRM.S
deleted file mode 100644
index 1948be63a..000000000
--- a/libc/sysv/consts/MSG_CONFIRM.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_CONFIRM,0x0800,0x0800,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_EOF.S b/libc/sysv/consts/MSG_EOF.S
deleted file mode 100644
index 3e8168a2a..000000000
--- a/libc/sysv/consts/MSG_EOF.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_EOF,0x0200,0x0200,0x0100,0x0100,0x0100,0,0,0
diff --git a/libc/sysv/consts/MSG_EOR.S b/libc/sysv/consts/MSG_EOR.S
deleted file mode 100644
index fe773b16a..000000000
--- a/libc/sysv/consts/MSG_EOR.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_EOR,0x80,0x80,8,8,8,8,8,0
diff --git a/libc/sysv/consts/MSG_ERRQUEUE.S b/libc/sysv/consts/MSG_ERRQUEUE.S
deleted file mode 100644
index 02f1934ff..000000000
--- a/libc/sysv/consts/MSG_ERRQUEUE.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_ERRQUEUE,0x2000,0x2000,0,0,0,0,0,0x1000
diff --git a/libc/sysv/consts/MSG_EXCEPT.S b/libc/sysv/consts/MSG_EXCEPT.S
deleted file mode 100644
index da072f0a9..000000000
--- a/libc/sysv/consts/MSG_EXCEPT.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_EXCEPT,0x2000,0x2000,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_FASTOPEN.S b/libc/sysv/consts/MSG_FASTOPEN.S
index ff034a75b..17aa7bab6 100644
--- a/libc/sysv/consts/MSG_FASTOPEN.S
+++ b/libc/sysv/consts/MSG_FASTOPEN.S
@@ -1,2 +1,2 @@
 #include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_FASTOPEN,0x20000000,0x20000000,0,0,0,0,0,0
+.syscon msg,MSG_FASTOPEN,0x20000000,0x20000000,-1,-1,-1,-1,-1,-1
diff --git a/libc/sysv/consts/MSG_FIN.S b/libc/sysv/consts/MSG_FIN.S
deleted file mode 100644
index f0631e333..000000000
--- a/libc/sysv/consts/MSG_FIN.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_FIN,0x0200,0x0200,0x0100,0x0100,0x0100,0,0,0
diff --git a/libc/sysv/consts/MSG_INFO.S b/libc/sysv/consts/MSG_INFO.S
deleted file mode 100644
index d882e3a75..000000000
--- a/libc/sysv/consts/MSG_INFO.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_INFO,12,12,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_MCAST.S b/libc/sysv/consts/MSG_MCAST.S
deleted file mode 100644
index 0f68f5321..000000000
--- a/libc/sysv/consts/MSG_MCAST.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_MCAST,0,0,0,0,0,0x200,0x200,0
diff --git a/libc/sysv/consts/MSG_MORE.S b/libc/sysv/consts/MSG_MORE.S
deleted file mode 100644
index fa8717d4f..000000000
--- a/libc/sysv/consts/MSG_MORE.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_MORE,0x8000,0x8000,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_NOERROR.S b/libc/sysv/consts/MSG_NOERROR.S
deleted file mode 100644
index 22764bb8d..000000000
--- a/libc/sysv/consts/MSG_NOERROR.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_NOERROR,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0
diff --git a/libc/sysv/consts/MSG_NOSIGNAL.S b/libc/sysv/consts/MSG_NOSIGNAL.S
index 48be7e922..1a0539eef 100644
--- a/libc/sysv/consts/MSG_NOSIGNAL.S
+++ b/libc/sysv/consts/MSG_NOSIGNAL.S
@@ -1,2 +1,2 @@
 #include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_NOSIGNAL,0x4000,0x4000,0x80000,0x80000,0x020000,0x0400,0x0400,0
+.syscon msg,MSG_NOSIGNAL,0x4000,0x4000,0x80000,0x80000,0x020000,0x0400,0x0400,0x10000000
diff --git a/libc/sysv/consts/MSG_NOTIFICATION.S b/libc/sysv/consts/MSG_NOTIFICATION.S
deleted file mode 100644
index 7503b5a50..000000000
--- a/libc/sysv/consts/MSG_NOTIFICATION.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_NOTIFICATION,0x8000,0x8000,0,0,0x2000,0,0x4000,0
diff --git a/libc/sysv/consts/MSG_PARITY_ERROR.S b/libc/sysv/consts/MSG_PARITY_ERROR.S
deleted file mode 100644
index 7abd7fafd..000000000
--- a/libc/sysv/consts/MSG_PARITY_ERROR.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_PARITY_ERROR,9,9,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_PROXY.S b/libc/sysv/consts/MSG_PROXY.S
deleted file mode 100644
index e6216ce64..000000000
--- a/libc/sysv/consts/MSG_PROXY.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_PROXY,0x10,0x10,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_RST.S b/libc/sysv/consts/MSG_RST.S
deleted file mode 100644
index 3bed0246b..000000000
--- a/libc/sysv/consts/MSG_RST.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_RST,0x1000,0x1000,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_STAT.S b/libc/sysv/consts/MSG_STAT.S
deleted file mode 100644
index cdee6a110..000000000
--- a/libc/sysv/consts/MSG_STAT.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_STAT,11,11,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_SYN.S b/libc/sysv/consts/MSG_SYN.S
deleted file mode 100644
index b57fbeb86..000000000
--- a/libc/sysv/consts/MSG_SYN.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_SYN,0x0400,0x0400,0,0,0,0,0,0
diff --git a/libc/sysv/consts/MSG_WAITFORONE.S b/libc/sysv/consts/MSG_WAITFORONE.S
deleted file mode 100644
index e89b311e2..000000000
--- a/libc/sysv/consts/MSG_WAITFORONE.S
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "libc/sysv/consts/syscon.internal.h"
-.syscon msg,MSG_WAITFORONE,0x010000,0x010000,0,0,0x080000,0,0x2000,0
diff --git a/libc/sysv/consts/msg.h b/libc/sysv/consts/msg.h
index 74deaca26..3694fc6f6 100644
--- a/libc/sysv/consts/msg.h
+++ b/libc/sysv/consts/msg.h
@@ -2,41 +2,18 @@
 #define COSMOPOLITAN_LIBC_SYSV_CONSTS_MSG_H_
 COSMOPOLITAN_C_START_
 
-extern const int MSG_BATCH;
-extern const int MSG_BCAST;
-extern const int MSG_CMSG_CLOEXEC;
-extern const int MSG_CONFIRM;
-extern const int MSG_CTRUNC;
-extern const int MSG_DONTROUTE;
 extern const int MSG_DONTWAIT;
-extern const int MSG_EOF;
-extern const int MSG_EOR;
-extern const int MSG_ERRQUEUE;
-extern const int MSG_EXCEPT;
-extern const int MSG_FASTOPEN;
-extern const int MSG_FIN;
-extern const int MSG_INFO;
-extern const int MSG_MCAST;
-extern const int MSG_MORE;
-extern const int MSG_NOERROR;
-extern const int MSG_NOSIGNAL;
-extern const int MSG_NOTIFICATION;
-extern const int MSG_OOB;
-extern const int MSG_PARITY_ERROR;
-extern const int MSG_PEEK;
-extern const int MSG_PROXY;
-extern const int MSG_RST;
-extern const int MSG_STAT;
-extern const int MSG_SYN;
-extern const int MSG_TRUNC;
 extern const int MSG_WAITALL;
-extern const int MSG_WAITFORONE;
+extern const int MSG_NOSIGNAL;
+extern const int MSG_TRUNC;
+extern const int MSG_CTRUNC;
+extern const int MSG_FASTOPEN; /* linux only */
 
 #define MSG_OOB       1
 #define MSG_PEEK      2
 #define MSG_DONTROUTE 4
 #define MSG_DONTWAIT  MSG_DONTWAIT
-#define MSG_FASTOPEN  MSG_FASTOPEN
+#define MSG_NOSIGNAL  MSG_NOSIGNAL
 #define MSG_WAITALL   MSG_WAITALL
 #define MSG_TRUNC     MSG_TRUNC
 #define MSG_CTRUNC    MSG_CTRUNC
diff --git a/test/posix/msg_nosignal_test.c b/test/posix/msg_nosignal_test.c
new file mode 100644
index 000000000..c164a4b9b
--- /dev/null
+++ b/test/posix/msg_nosignal_test.c
@@ -0,0 +1,196 @@
+// Copyright 2024 Justine Alexandra Roberts Tunney
+//
+// Permission to use, copy, modify, and/or distribute this software for
+// any purpose with or without fee is hereby granted, provided that the
+// above copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <arpa/inet.h>
+#include <cosmo.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdatomic.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/**
+ * @fileoverview send(MSG_NOSIGNAL) test
+ *
+ * It's possible when writing to a socket for SIGPIPE to be raised. It
+ * can happen for a variety of reasons. The one reason that has broad
+ * consensus across OSes and is officially documented, is if shutdown()
+ * is used on the local end.
+ */
+
+struct sockaddr_in serv_addr;
+atomic_bool g_ready_for_conn;
+atomic_bool g_ready_for_data;
+atomic_bool g_ready_for_more;
+atomic_bool g_ready_for_exit;
+volatile sig_atomic_t g_got_signal;
+
+void onsig(int sig) {
+  g_got_signal = sig;
+}
+
+void *server_thread(void *arg) {
+  socklen_t len;
+  int server, client;
+  struct sockaddr_in cli_addr;
+
+  // create listening socket
+  server = socket(AF_INET, SOCK_STREAM, 0);
+  if (server == -1) {
+    perror("socket");
+    exit(10);
+  }
+
+  // initialize server address
+  memset(&serv_addr, 0, sizeof(serv_addr));
+  serv_addr.sin_family = AF_INET;
+  serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  serv_addr.sin_port = htons(0);
+
+  // bind socket
+  if (bind(server, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {
+    perror("bind");
+    exit(11);
+  }
+
+  // get assigned port
+  len = sizeof(serv_addr);
+  if (getsockname(server, (struct sockaddr *)&serv_addr, &len)) {
+    perror("getsockname");
+    exit(12);
+  }
+
+  // listen on the socket
+  if (listen(server, SOMAXCONN)) {
+    perror("listen");
+    exit(13);
+  }
+
+  // wake main thread
+  g_ready_for_conn = true;
+
+  // accept connection
+  len = sizeof(cli_addr);
+  client = accept(server, (struct sockaddr *)&cli_addr, &len);
+  if (client == -1) {
+    perror("accept");
+    exit(14);
+  }
+
+  // wake main thread
+  g_ready_for_data = true;
+
+  // wait for thread
+  for (;;)
+    if (g_ready_for_exit)
+      break;
+
+  // close sockets
+  if (close(client))
+    exit(29);
+  if (close(server))
+    exit(28);
+
+  return 0;
+}
+
+int main() {
+
+  // create server thread
+  pthread_t th;
+  if (pthread_create(&th, 0, server_thread, 0))
+    return 1;
+
+  // wait for thread
+  for (;;)
+    if (g_ready_for_conn)
+      break;
+
+  // create socket
+  int client = socket(AF_INET, SOCK_STREAM, 0);
+  if (client == -1) {
+    perror("socket");
+    return 2;
+  }
+
+  // connect to server
+  if (connect(client, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
+    perror("connect");
+    return 3;
+  }
+
+  // wait for thread
+  for (;;)
+    if (g_ready_for_data)
+      break;
+
+  // handle signals
+  struct sigaction sa;
+  sa.sa_flags = 0;
+  sa.sa_handler = onsig;
+  sigemptyset(&sa.sa_mask);
+  sigaction(SIGPIPE, &sa, 0);
+
+  // half close socket
+  if (shutdown(client, SHUT_WR))
+    return 15;
+
+  // send first transmission
+  int rc;
+  for (;;) {
+    rc = write(client, "x", 1);
+    if (rc == 1)
+      continue;
+    if (rc != -1)
+      return 4;
+    if (errno != EPIPE) {
+      perror("write");
+      return 5;
+    }
+    // NetBSD is oddly lazy about sending SIGPIPE
+    if (IsNetbsd())
+      for (;;)
+        if (g_got_signal)
+          break;
+    if (g_got_signal != SIGPIPE) {
+      fprintf(stderr, "expected SIGPIPE but got %s\n", strsignal(g_got_signal));
+      return 6;
+    }
+    g_got_signal = 0;
+    break;
+  }
+
+  // send first transmission
+  rc = send(client, "x", 1, MSG_NOSIGNAL);
+  if (rc != -1)
+    return 7;
+  if (errno != EPIPE)
+    return 8;
+  if (g_got_signal)
+    return 9;
+
+  g_ready_for_exit = true;
+
+  if (pthread_join(th, 0))
+    return 6;
+}
diff --git a/test/posix/msg_waitall_test.c b/test/posix/msg_waitall_test.c
new file mode 100644
index 000000000..99942383d
--- /dev/null
+++ b/test/posix/msg_waitall_test.c
@@ -0,0 +1,207 @@
+// Copyright 2024 Justine Alexandra Roberts Tunney
+//
+// Permission to use, copy, modify, and/or distribute this software for
+// any purpose with or without fee is hereby granted, provided that the
+// above copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <arpa/inet.h>
+#include <cosmo.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdatomic.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/**
+ * @fileoverview recv(MSG_WAITALL) test
+ */
+
+struct sockaddr_in serv_addr;
+atomic_bool g_ready_for_conn;
+atomic_bool g_ready_for_data;
+atomic_bool g_ready_for_more;
+atomic_bool g_ready_for_exit;
+
+void *server_thread(void *arg) {
+  socklen_t len;
+  int server, client;
+  struct sockaddr_in cli_addr;
+
+  // create listening socket
+  server = socket(AF_INET, SOCK_STREAM, 0);
+  if (server == -1) {
+    perror("socket");
+    exit(10);
+  }
+
+  // initialize server address
+  memset(&serv_addr, 0, sizeof(serv_addr));
+  serv_addr.sin_family = AF_INET;
+  serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  serv_addr.sin_port = htons(0);
+
+  // bind socket
+  if (bind(server, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {
+    perror("bind");
+    exit(11);
+  }
+
+  // get assigned port
+  len = sizeof(serv_addr);
+  if (getsockname(server, (struct sockaddr *)&serv_addr, &len)) {
+    perror("getsockname");
+    exit(12);
+  }
+
+  // listen on the socket
+  if (listen(server, SOMAXCONN)) {
+    perror("listen");
+    exit(13);
+  }
+
+  // wake main thread
+  g_ready_for_conn = true;
+
+  // accept connection
+  len = sizeof(cli_addr);
+  client = accept(server, (struct sockaddr *)&cli_addr, &len);
+  if (client == -1) {
+    perror("accept");
+    exit(14);
+  }
+
+  // check waitall + dontwait
+  char buf[2];
+  int rc = recv(client, buf, 2, MSG_WAITALL | MSG_DONTWAIT);
+  if (rc != -1)
+    exit(15);
+  if (errno != EAGAIN)
+    exit(16);
+
+  // wake main thread
+  g_ready_for_data = true;
+
+  // check peek
+  rc = recv(client, buf, 2, MSG_PEEK);
+  if (rc == -1) {
+    perror("recv1");
+    exit(17);
+  }
+  if (rc != 1)
+    exit(18);
+  if (buf[0] != 'x')
+    exit(19);
+
+  // check read() has @restartable behavior
+  rc = recv(client, buf, 2, MSG_WAITALL);
+  if (rc == -1) {
+    perror("recv2");
+    exit(21);
+  }
+  if (rc != 2)
+    exit(22);
+  if (buf[0] != 'x')
+    exit(23);
+  if (buf[1] != 'y')
+    exit(24);
+
+  // wake main thread
+  g_ready_for_more = true;
+
+  // check normal recv won't wait
+  rc = read(client, buf, 2);
+  if (rc == -1) {
+    perror("recv3");
+    exit(25);
+  }
+  if (rc != 1)
+    exit(26);
+  if (buf[0] != 'x')
+    exit(27);
+
+  // wait for main thread
+  for (;;)
+    if (g_ready_for_exit)
+      break;
+
+  // close listening socket
+  if (close(server))
+    exit(28);
+  if (close(client))
+    exit(29);
+  return 0;
+}
+
+int main() {
+
+  // create server thread
+  pthread_t th;
+  if (pthread_create(&th, 0, server_thread, 0))
+    return 1;
+
+  // wait for thread
+  for (;;)
+    if (g_ready_for_conn)
+      break;
+
+  // create socket
+  int client = socket(AF_INET, SOCK_STREAM, 0);
+  if (client == -1) {
+    perror("socket");
+    return 2;
+  }
+
+  // connect to server
+  if (connect(client, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {
+    perror("connect");
+    return 3;
+  }
+
+  // wait for thread
+  for (;;)
+    if (g_ready_for_data)
+      break;
+
+  // send first transmission
+  usleep(100e3);
+  if (write(client, "x", 1) != 1)
+    return 4;
+  usleep(100e3);
+  if (write(client, "y", 1) != 1)
+    return 5;
+
+  // wait for thread
+  for (;;)
+    if (g_ready_for_more)
+      break;
+
+  // send second transmission
+  usleep(100e3);
+  if (write(client, "x", 1) != 1)
+    return 4;
+  usleep(100e3);
+  if (write(client, "y", 1) != 1)
+    return 5;
+
+  g_ready_for_exit = true;
+
+  if (pthread_join(th, 0))
+    return 6;
+}
diff --git a/third_party/lua/lunix.c b/third_party/lua/lunix.c
index 06cd1541b..9a8b44877 100644
--- a/third_party/lua/lunix.c
+++ b/third_party/lua/lunix.c
@@ -3439,12 +3439,14 @@ int LuaUnix(lua_State *L) {
   LuaSetIntField(L, "SHUT_RDWR", SHUT_RDWR);
 
   // recvfrom() / sendto() flags
-  LuaSetIntField(L, "MSG_WAITALL", MSG_WAITALL);
-  LuaSetIntField(L, "MSG_DONTROUTE", MSG_DONTROUTE);
-  LuaSetIntField(L, "MSG_PEEK", MSG_PEEK);
   LuaSetIntField(L, "MSG_OOB", MSG_OOB);
+  LuaSetIntField(L, "MSG_PEEK", MSG_PEEK);
+  LuaSetIntField(L, "MSG_DONTROUTE", MSG_DONTROUTE);
+  LuaSetIntField(L, "MSG_DONTWAIT", MSG_DONTWAIT);
   LuaSetIntField(L, "MSG_NOSIGNAL", MSG_NOSIGNAL);
-  LuaSetIntField(L, "MSG_MORE", MSG_MORE);
+  LuaSetIntField(L, "MSG_WAITALL", MSG_WAITALL);
+  LuaSetIntField(L, "MSG_TRUNC", MSG_TRUNC);
+  LuaSetIntField(L, "MSG_CTRUNC", MSG_CTRUNC);
 
   // readdir() type
   LuaSetIntField(L, "DT_UNKNOWN", DT_UNKNOWN);
diff --git a/third_party/nsync/testing/cv_wait_example_test.c b/third_party/nsync/testing/cv_wait_example.c
similarity index 99%
rename from third_party/nsync/testing/cv_wait_example_test.c
rename to third_party/nsync/testing/cv_wait_example.c
index d365d4f9d..f94092987 100644
--- a/third_party/nsync/testing/cv_wait_example_test.c
+++ b/third_party/nsync/testing/cv_wait_example.c
@@ -25,6 +25,7 @@
 #include "third_party/nsync/testing/closure.h"
 #include "third_party/nsync/testing/smprintf.h"
 #include "third_party/nsync/testing/testing.h"
+#include "libc/dce.h"
 #include "third_party/nsync/testing/time_extra.h"
 
 /* Example use of CV.wait():  A priority queue of strings whose
diff --git a/third_party/python/Modules/socketmodule.c b/third_party/python/Modules/socketmodule.c
index 03680235b..a8e368268 100644
--- a/third_party/python/Modules/socketmodule.c
+++ b/third_party/python/Modules/socketmodule.c
@@ -6790,24 +6790,9 @@ PyInit__socket(void)
     PyModule_AddIntMacro(m, MSG_TRUNC);
     PyModule_AddIntMacro(m, MSG_CTRUNC);
     PyModule_AddIntMacro(m, MSG_WAITALL);
-    if (MSG_DONTWAIT) PyModule_AddIntMacro(m, MSG_DONTWAIT);
-    if (MSG_EOR) PyModule_AddIntMacro(m, MSG_EOR);
-    if (MSG_NOSIGNAL) PyModule_AddIntMacro(m, MSG_NOSIGNAL);
-    if (MSG_BCAST) PyModule_AddIntMacro(m, MSG_BCAST);
-    if (MSG_MCAST) PyModule_AddIntMacro(m, MSG_MCAST);
-    if (MSG_CMSG_CLOEXEC) PyModule_AddIntMacro(m, MSG_CMSG_CLOEXEC);
-    if (MSG_ERRQUEUE) PyModule_AddIntMacro(m, MSG_ERRQUEUE);
-    if (MSG_CONFIRM) PyModule_AddIntMacro(m, MSG_CONFIRM);
-    if (MSG_MORE) PyModule_AddIntMacro(m, MSG_MORE);
-    if (MSG_NOTIFICATION) PyModule_AddIntMacro(m, MSG_NOTIFICATION);
-    if (MSG_EOF) PyModule_AddIntMacro(m, MSG_EOF);
-    if (MSG_FASTOPEN) PyModule_AddIntMacro(m, MSG_FASTOPEN);
-#ifdef MSG_BTAG
-    if (MSG_BTAG) PyModule_AddIntMacro(m, MSG_BTAG);
-#endif
-#ifdef MSG_ETAG
-    if (MSG_ETAG) PyModule_AddIntMacro(m, MSG_ETAG);
-#endif
+    PyModule_AddIntMacro(m, MSG_DONTWAIT);
+    PyModule_AddIntMacro(m, MSG_NOSIGNAL);
+    if (MSG_FASTOPEN != -1) PyModule_AddIntMacro(m, MSG_FASTOPEN);
 
     /* Protocol level and numbers, usable for [gs]etsockopt */
     PyModule_AddIntMacro(m, SOL_SOCKET);