| /* |
| * Copyright 2026 The Emscripten Authors. All rights reserved. |
| * Emscripten is available under two separate licenses, the MIT license and the |
| * University of Illinois/NCSA Open Source License. Both these licenses can be |
| * found in the LICENSE file. |
| * |
| * Write-side backpressure. We connect to a sink server (argv[1]) that accepts |
| * but never reads, then send non-blocking until the kernel + node buffers fill |
| * and send() reports EAGAIN. That proves writes are bounded rather than |
| * buffered without limit. Plain POSIX, also runs natively. |
| */ |
| |
| #include <arpa/inet.h> |
| #include <assert.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <netinet/in.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/select.h> |
| #include <sys/socket.h> |
| #include <sys/time.h> |
| #include <unistd.h> |
| |
| #ifdef __EMSCRIPTEN__ |
| #include <emscripten.h> |
| #endif |
| |
| int fd = -1; |
| bool connected = false; |
| char chunk[65536]; |
| // Safety cap so a misbehaving stack that never backpressures can't run forever. |
| long long sent_total = 0; |
| const long long CAP = 512LL * 1024 * 1024; |
| |
| void test_success(void) { |
| printf("done\n"); |
| if (fd >= 0) close(fd); |
| #ifdef __EMSCRIPTEN__ |
| emscripten_cancel_main_loop(); |
| #else |
| exit(0); |
| #endif |
| } |
| |
| void main_loop(void) { |
| fd_set fdw; |
| struct timeval tv = {0}; |
| FD_ZERO(&fdw); |
| FD_SET(fd, &fdw); |
| select(64, NULL, &fdw, NULL, &tv); |
| |
| if (!connected && FD_ISSET(fd, &fdw)) { |
| int err = 0; |
| socklen_t l = sizeof(err); |
| getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &l); |
| assert(err == 0 && "connect failed"); |
| connected = true; |
| } |
| |
| if (!connected) return; |
| |
| // Push hard. The peer never reads, so this must eventually would-block. |
| while (sent_total < CAP) { |
| ssize_t n = send(fd, chunk, sizeof(chunk), 0); |
| if (n < 0) { |
| assert((errno == EAGAIN || errno == EWOULDBLOCK) && "send failed"); |
| printf("backpressure after %lld bytes\n", sent_total); |
| test_success(); |
| return; |
| } |
| sent_total += n; |
| } |
| assert(false && "no backpressure before the safety cap"); |
| } |
| |
| int main(int argc, char** argv) { |
| assert(argc > 1 && "usage: test_tcp_backpressure <port>"); |
| |
| fd = socket(AF_INET, SOCK_STREAM, 0); |
| assert(fd >= 0); |
| fcntl(fd, F_SETFL, O_NONBLOCK); |
| |
| struct sockaddr_in dest; |
| memset(&dest, 0, sizeof(dest)); |
| dest.sin_family = AF_INET; |
| dest.sin_port = htons(atoi(argv[1])); |
| inet_pton(AF_INET, "127.0.0.1", &dest.sin_addr); |
| |
| int r = connect(fd, (struct sockaddr*)&dest, sizeof(dest)); |
| assert((r == 0 || errno == EINPROGRESS) && "connect"); |
| |
| #ifdef __EMSCRIPTEN__ |
| emscripten_set_main_loop(main_loop, 0, 0); |
| #else |
| while (1) { |
| main_loop(); |
| usleep(1000); |
| } |
| #endif |
| return 0; |
| } |