AtlatestRepositorysigil-websocket

sigil-websocket / tree / test / integrationshort-socket-writes.c

1/* Linux test instrument: force short writes and EAGAIN on nonblocking
2 * stream sockets. Run ONLY in an isolated client via LD_PRELOAD.
3 * cc -shared -fPIC -o short-socket-writes.so short-socket-writes.c -ldl
4 * SIGIL_SHORT_WRITE_LOG optionally records counts, never payload bytes. */
5#define _GNU_SOURCE
6#include <dlfcn.h>
7#include <sys/socket.h>
8#include <fcntl.h>
9#include <errno.h>
10#include <unistd.h>
11#include <stdio.h>
12#include <stdlib.h>
14static unsigned short_writes, would_block;
15static int constrain(int fd, size_t *length) {
16 int type;
17 socklen_t size = sizeof(type);
18 if (*length <= 4096 || !(fcntl(fd, F_GETFL) & O_NONBLOCK) ||
19 getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &size) != 0 ||
20 type != SOCK_STREAM) return 0;
21 if (short_writes > would_block) {
22 ++would_block;
23 errno = EAGAIN;
24 return -1;
25 }
26 ++short_writes;
27 *length = 4096;
28 return 0;
31ssize_t send(int fd, const void *bytes, size_t length, int flags) {
32 static ssize_t (*native_send)(int, const void *, size_t, int);
33 if (!native_send) native_send = dlsym(RTLD_NEXT, "send");
34 if (constrain(fd, &length) < 0) return -1;
35 return native_send(fd, bytes, length, flags);
38ssize_t write(int fd, const void *bytes, size_t length) {
39 static ssize_t (*native_write)(int, const void *, size_t);
40 if (!native_write) native_write = dlsym(RTLD_NEXT, "write");
41 if (constrain(fd, &length) < 0) return -1;
42 return native_write(fd, bytes, length);
45__attribute__((destructor)) static void record_counts(void) {
46 const char *path = getenv("SIGIL_SHORT_WRITE_LOG");
47 if (!path || (!short_writes && !would_block)) return;
48 int fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0600);
49 if (fd < 0) return;
50 char line[128];
51 int length = snprintf(line, sizeof(line), "%ld %u %u\n",
52 (long)getpid(), short_writes, would_block);
53 if (length > 0 && (size_t)length < sizeof(line)) write(fd, line, length);
54 close(fd);