fix ENOBUFS errors with backoff+retry

This commit is contained in:
Alexander Jacobsen 2026-07-18 01:21:41 +02:00
parent ee414035de
commit 52ee2fd391
2 changed files with 23 additions and 11 deletions

View file

@ -216,18 +216,30 @@ static void *worker_main(void *arg)
while (next < PACKET_COUNT) { while (next < PACKET_COUNT) {
int sent = sendmmsg(fd, &messages[next], int sent = sendmmsg(fd, &messages[next],
(unsigned int)(PACKET_COUNT - next), 0); (unsigned int)(PACKET_COUNT - next), 0);
if (sent == -1) { if (sent >= 0) {
if (errno == EINTR) next += sent;
continue; continue;
/* ECONNREFUSED is stale ICMP feedback on a connected }
* UDP socket; EAGAIN means the send buffer is full. switch (errno) {
* Both are transient - repaint and keep sending. */ case EINTR:
if (errno != ECONNREFUSED && errno != EAGAIN && continue; /* interrupted before sending - retry now */
errno != EWOULDBLOCK) case ENOBUFS: /* interface send queue full: we outrun the link */
perror("sendmmsg"); case EAGAIN:
#if EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
/* Transient back-pressure. Back off briefly so the queue
* drains (rather than spinning on failing syscalls), then
* resend the same batch - no need to repaint. */
usleep(200);
continue;
case ECONNREFUSED:
break; /* stale ICMP on connected UDP; repaint and retry */
default:
perror("sendmmsg");
break; break;
} }
next += sent; break; /* ECONNREFUSED / unexpected: stop, repaint, retry */
} }
} }

View file

@ -26,7 +26,7 @@
* to avoid IP fragmentation (e.g. 207 pixels ~= 1451 B fits a 1500 B link). * to avoid IP fragmentation (e.g. 207 pixels ~= 1451 B fits a 1500 B link).
* Override at build time with -DPIXELS_PER_PACKET=N. */ * Override at build time with -DPIXELS_PER_PACKET=N. */
#ifndef PIXELS_PER_PACKET #ifndef PIXELS_PER_PACKET
# define PIXELS_PER_PACKET 120 # define PIXELS_PER_PACKET 200
#endif #endif
#pragma pack(push, 1) #pragma pack(push, 1)