]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Fix bug which caused dnsmasq to become unresponsive when an interface goes.
authorSimon Kelley <simon@thekelleys.org.uk>
Thu, 18 Sep 2014 21:08:58 +0000 (22:08 +0100)
committerSimon Kelley <simon@thekelleys.org.uk>
Thu, 18 Sep 2014 21:08:58 +0000 (22:08 +0100)
CHANGELOG
src/util.c

index 00f0480daad7e85d25b2a2b39f4ccf2ba715000a..35093ada6e91ab46f4206bfb81647d10dc6b820d 100644 (file)
--- 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
index df751c7f8ea4aad8b1d4e4ef025e39aa7c602097..a729f339e219d3e24fd28ab2ac0e5410da2d0f8e 100644 (file)
@@ -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;
 }