Skip to content

Commit 774c67f

Browse files
committed
Make send() block in non-blocking mode
1 parent 3c58ecd commit 774c67f

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

libc/sock/send-nt.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,14 @@ textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
5454
ssize_t rc;
5555
struct Fd *f = g_fds.p + fd;
5656
sigset_t m = __sig_block();
57-
bool nonblock = (f->flags & O_NONBLOCK) || (flags & _MSG_DONTWAIT);
57+
58+
// we don't check O_NONBLOCK because we want to avoid needing to call
59+
// WSAPoll() every time we write() to a non-blocking socket. WIN32 is
60+
// unsafe at canceling socket sends. lots of code doesn't check write
61+
// return status. good programs that sincerely want to avoid blocking
62+
// on send() operations should have already called poll() beforehand.
63+
bool nonblock = flags & _MSG_DONTWAIT;
64+
5865
flags &= ~_MSG_DONTWAIT;
5966
rc = __winsock_block(f->handle, flags, -nonblock, f->sndtimeo, m,
6067
sys_send_nt_start, &(struct SendArgs){iov, iovlen});

libc/sock/send.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@
3030
/**
3131
* Sends data to network socket.
3232
*
33+
* Calling `send(fd, p, n, 0)` is equivalent to `write(fd, p, n)`.
34+
*
35+
* On Windows, calling send() or write() on a socket in `O_NONBLOCK`
36+
* mode will block. This is done for many reasons. First, most UNIX OSes
37+
* have a similar behavior, due to how little code checks the return
38+
* status of write(). Secondly, WIN32 has bugs that prevent us from
39+
* canceling an overlapped WSASend() operation safely. Programs that
40+
* want to avoid send() blocking should call poll() beforehand with the
41+
* POLLOUT flag to test when the socket can safely be written without
42+
* blocking. It's also possible to pass `MSG_DONTWAIT` via `flags` in
43+
* which case send() will do this for you automatically.
44+
*
3345
* @param fd is the file descriptor returned by socket()
3446
* @param buf is the data to send, which we'll copy if necessary
3547
* @param size is the byte-length of buf

0 commit comments

Comments
 (0)