From 134cd2b8c78e5259e2d6bb54f9022f56676c78f1 Mon Sep 17 00:00:00 2001 From: jimmyolo Date: Fri, 4 Sep 2026 01:40:48 +0800 Subject: [PATCH 1/2] Stop the read_more loop once the poll mask no longer has READABLE read_more re-reads whenever one recv filled the buffer, so that a hangup queued in the same iteration cannot close the socket before the data is drained. That is still done here. What changes: if on_data de-armed LIBUS_SOCKET_READABLE (us_poll_change from inside the callback, which is how a consumer says "stop"), the loop now honours it instead of reading until close. Before, a paused consumer kept receiving 512 KB per pass while the peer's window stayed open; measured 2.8 MB queued against a 64 KB mark on a pulsed-drain peer. --- src/loop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/loop.c b/src/loop.c index 8f3b696..98a5d90 100644 --- a/src/loop.c +++ b/src/loop.c @@ -360,7 +360,8 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int events) /* If we filled the entire recv buffer, we need to immediately read again since otherwise a * pending hangup event in the same even loop iteration can close the socket before we get * the chance to read again next iteration */ - if (length == LIBUS_RECV_BUFFER_LENGTH && s && !us_socket_is_closed(0, s)) { + if (length == LIBUS_RECV_BUFFER_LENGTH && s && !us_socket_is_closed(0, s) + && (us_poll_events(&s->p) & LIBUS_SOCKET_READABLE)) { goto read_more; } From 5b9e9a8dccc566786a3464caa3e32aa6e07cdbd6 Mon Sep 17 00:00:00 2001 From: jimmyolo Date: Fri, 4 Sep 2026 01:40:48 +0800 Subject: [PATCH 2/2] Skip bsd_set_nonblocking on sockets created with SOCK_NONBLOCK bsd_create_socket and bsd_accept_socket already pass SOCK_NONBLOCK where the platform has it, then call bsd_set_nonblocking anyway: F_GETFL plus F_SETFL on a descriptor that is already non-blocking. Four fcntl per connect+close (client and accepted socket) that do nothing, 4.00 to 0.00 under strace -c. The #else keeps the fcntl pair for platforms without the flag. --- src/bsd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bsd.c b/src/bsd.c index d35eae9..02c65cc 100644 --- a/src/bsd.c +++ b/src/bsd.c @@ -306,7 +306,11 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_socket(int domain, int type, int protocol) { LIBUS_SOCKET_DESCRIPTOR created_fd = socket(domain, type | flags, protocol); +#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) + return apple_no_sigpipe(created_fd); +#else return bsd_set_nonblocking(apple_no_sigpipe(created_fd)); +#endif } void bsd_close_socket(LIBUS_SOCKET_DESCRIPTOR fd) { @@ -400,7 +404,11 @@ LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd internal_finalize_bsd_addr(addr); +#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) + return apple_no_sigpipe(accepted_fd); +#else return bsd_set_nonblocking(apple_no_sigpipe(accepted_fd)); +#endif } int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags) {