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) {
int sent = sendmmsg(fd, &messages[next],
(unsigned int)(PACKET_COUNT - next), 0);
if (sent == -1) {
if (errno == EINTR)
if (sent >= 0) {
next += sent;
continue;
/* ECONNREFUSED is stale ICMP feedback on a connected
* UDP socket; EAGAIN means the send buffer is full.
* Both are transient - repaint and keep sending. */
if (errno != ECONNREFUSED && errno != EAGAIN &&
errno != EWOULDBLOCK)
}
switch (errno) {
case EINTR:
continue; /* interrupted before sending - retry now */
case ENOBUFS: /* interface send queue full: we outrun the link */
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;
}
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).
* Override at build time with -DPIXELS_PER_PACKET=N. */
#ifndef PIXELS_PER_PACKET
# define PIXELS_PER_PACKET 120
# define PIXELS_PER_PACKET 200
#endif
#pragma pack(push, 1)