From 5782649ad95382dd558df97b33b64e854d8789fb Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 18 Sep 2014 22:08:58 +0100 Subject: Fix bug which caused dnsmasq to become unresponsive when an interface goes. --- CHANGELOG | 4 ++++ src/util.c | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 00f0480..35093ad 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -33,6 +33,10 @@ version 2.72 Fix bug when resulted in NXDOMAIN answers instead of NODATA in some circumstances. + + Fix bug which caused dnsmasq to become unresponsive if it + failed to send packets due to a network interface disappearing. + Thanks to Niels Peen for spotting this. version 2.71 diff --git a/src/util.c b/src/util.c index df751c7..a729f33 100644 --- a/src/util.c +++ b/src/util.c @@ -570,18 +570,28 @@ void bump_maxfd(int fd, int *max) int retry_send(void) { - struct timespec waiter; + /* Linux kernels can return EAGAIN in perpetuity when calling + sendmsg() and the relevant interface has gone. Here we loop + retrying in EAGAIN for 1 second max, to avoid this hanging + dnsmasq. */ + + static int retries = 0; + struct timespec waiter; + if (errno == EAGAIN || errno == EWOULDBLOCK) { waiter.tv_sec = 0; waiter.tv_nsec = 10000; nanosleep(&waiter, NULL); - return 1; + if (retries++ < 1000) + return 1; } + + retries = 0; if (errno == EINTR) return 1; - + return 0; } -- cgit v1.2.1