diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2014-09-18 22:08:58 +0100 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2014-09-18 22:08:58 +0100 |
commit | 5782649ad95382dd558df97b33b64e854d8789fb (patch) | |
tree | b61b65ebce0e7eb5fa99ee4e5532133138589201 | |
parent | 288df49c96bb736a0cce203c7cbf7a1408dc99d6 (diff) | |
download | dnsmasq-5782649ad95382dd558df97b33b64e854d8789fb.tar.gz |
Fix bug which caused dnsmasq to become unresponsive when an interface goes.
-rw-r--r-- | CHANGELOG | 4 | ||||
-rw-r--r-- | src/util.c | 16 |
2 files changed, 17 insertions, 3 deletions
@@ -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 @@ -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; } |