]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Fix boilerplate code for re-running system calls on EINTR and EAGAIN etc.
authorSimon Kelley <simon@thekelleys.org.uk>
Wed, 11 Mar 2015 21:36:30 +0000 (21:36 +0000)
committerSimon Kelley <simon@thekelleys.org.uk>
Wed, 11 Mar 2015 21:36:30 +0000 (21:36 +0000)
The nasty code with static variable in retry_send() which
avoids looping forever needs to be called on success of the syscall,
to reset the static variable.

src/bpf.c
src/dhcp.c
src/dhcp6.c
src/dnsmasq.c
src/dnsmasq.h
src/forward.c
src/ipset.c
src/loop.c
src/netlink.c
src/radv.c
src/util.c

index 997d87421bed2e59d74e625b06d6b0cefc673677..a066641f969f0cd0b9ebd3700a1608bb57b56355 100644 (file)
--- a/src/bpf.c
+++ b/src/bpf.c
@@ -359,7 +359,7 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
   iov[3].iov_base = mess;
   iov[3].iov_len = len;
 
-  while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
+  while (retry_send(writev(daemon->dhcp_raw_fd, iov, 4)));
 }
 
 #endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
index f29be9b489a78b1ae969ea4e5934cfe2424ce96b..5c3089ab94ffdc37c760ccc7ec9ff381ce98507e 100644 (file)
@@ -443,7 +443,7 @@ void dhcp_packet(time_t now, int pxe_fd)
   setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
 #endif
   
-  while(sendmsg(fd, &msg, 0) == -1 && retry_send());
+  while(retry_send(sendmsg(fd, &msg, 0)));
 }
  
 /* check against secondary interface addresses */
index c7144f5fee7ce545766b4e7126f1138327274e1b..ee2aa5d3bf3c2eb9b949bf86f8579c75eeeedcc7 100644 (file)
@@ -225,9 +225,9 @@ void dhcp6_packet(time_t now)
   if (port != 0)
     {
       from.sin6_port = htons(port);
-      while (sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, save_counter(0)
-                   0, (struct sockaddr *)&from, sizeof(from)) == -1 &&
-          retry_send());
+      while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base
+                              save_counter(0), 0, (struct sockaddr *)&from, 
+                              sizeof(from))));
     }
 }
 
index f3e5bcffec4f8cd2b054b53eba616a7f25cef1cb..b784951950d400745bce96bfee04bdd0c11737a1 100644 (file)
@@ -444,7 +444,7 @@ int main (int argc, char **argv)
              char *msg;
 
              /* close our copy of write-end */
-             close(err_pipe[1]);
+             while (retry_send(close(err_pipe[1])));
              
              /* check for errors after the fork */
              if (read_event(err_pipe[0], &ev, &msg))
@@ -453,7 +453,7 @@ int main (int argc, char **argv)
              _exit(EC_GOOD);
            } 
          
-         close(err_pipe[0]);
+         while (retry_send(close(err_pipe[0])));
 
          /* NO calls to die() from here on. */
          
@@ -505,10 +505,12 @@ int main (int argc, char **argv)
            {
              if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
                err = 1;
-             
-             while (!err && close(fd) == -1)
-               if (!retry_send())
-                 err = 1;
+             else 
+               {
+                 while (retry_send(close(fd)));
+                 if (errno != 0)
+                   err = 1;
+               }
            }
 
          if (err)
@@ -813,7 +815,7 @@ int main (int argc, char **argv)
 
   /* finished start-up - release original process */
   if (err_pipe[1] != -1)
-    close(err_pipe[1]);
+    while (retry_send(close(err_pipe[1])));
   
   if (daemon->port != 0)
     check_servers();
@@ -1319,7 +1321,7 @@ static void async_event(int pipe, time_t now)
            do {
              helper_write();
            } while (!helper_buf_empty() || do_script_run(now));
-           close(daemon->helperfd);
+           while (retry_send(close(daemon->helperfd)));
          }
 #endif
        
@@ -1544,7 +1546,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
          
          if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
            {
-             close(confd);
+             while (retry_send(close(confd)));
              continue;
            }
          
@@ -1609,7 +1611,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
          if (!client_ok)
            {
              shutdown(confd, SHUT_RDWR);
-             close(confd);
+             while (retry_send(close(confd)));
            }
 #ifndef NO_FORK
          else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
@@ -1624,7 +1626,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
                        break;
                      }
                }
-             close(confd);
+             while (retry_send(close(confd)));
 
              /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
              daemon->log_id += TCP_MAX_QUERIES;
@@ -1669,7 +1671,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
              buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
               
              shutdown(confd, SHUT_RDWR);
-             close(confd);
+             while (retry_send(close(confd)));
              
              if (buff)
                free(buff);
@@ -1678,7 +1680,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
                if (s->tcpfd != -1)
                  {
                    shutdown(s->tcpfd, SHUT_RDWR);
-                   close(s->tcpfd);
+                   while (retry_send(close(s->tcpfd)));
                  }
 #ifndef NO_FORK                   
              if (!option_bool(OPT_DEBUG))
@@ -1756,9 +1758,8 @@ int icmp_ping(struct in_addr addr)
     j = (j & 0xffff) + (j >> 16);  
   packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
   
-  while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0, 
-               (struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
-        retry_send());
+  while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0, 
+                          (struct sockaddr *)&saddr, sizeof(saddr))));
   
   for (now = start = dnsmasq_time(); 
        difftime(now, start) < (float)PING_WAIT;)
@@ -1820,7 +1821,7 @@ int icmp_ping(struct in_addr addr)
     }
   
 #if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
-  close(fd);
+  while (retry_send(close(fd)));
 #else
   opt = 1;
   setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
index fc7259881358cbcb3abef65cf117bfe4482fa4f5..de95d0e875e3d357f4f3007ffaa2bf6f9b0547a4 100644 (file)
@@ -1177,7 +1177,7 @@ int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
 u64 addr6part(struct in6_addr *addr);
 void setaddr6part(struct in6_addr *addr, u64 host);
 #endif
-int retry_send(void);
+int retry_send(ssize_t rc);
 void prettyprint_time(char *buf, unsigned int t);
 int prettyprint_addr(union mysockaddr *addr, char *buf);
 int parse_hex(char *in, unsigned char *out, int maxlen, 
index 438e9fa490b8164cba9e9f73c332dda5f72a84e8..7c0fa8da3fdf611d6464f49fed5f812edc845ee4 100644 (file)
@@ -103,15 +103,11 @@ int send_from(int fd, int nowild, char *packet, size_t len,
 #endif
     }
   
-  while (sendmsg(fd, &msg, 0) == -1)
+  while (retry_send(sendmsg(fd, &msg, 0)));
+
+  /* If interface is still in DAD, EINVAL results - ignore that. */
+  if (errno != 0 && errno != EINVAL)
     {
-      if (retry_send())
-       continue;
-      
-      /* If interface is still in DAD, EINVAL results - ignore that. */
-      if (errno == EINVAL)
-       break;
-      
       my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
       return 0;
     }
@@ -297,9 +293,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
                fd = forward->rfd4->fd;
            }
          
-         while (sendto(fd, (char *)header, plen, 0,
-                       &forward->sentto->addr.sa,
-                       sa_len(&forward->sentto->addr)) == -1 && retry_send());
+         while (retry_send( sendto(fd, (char *)header, plen, 0,
+                                   &forward->sentto->addr.sa,
+                                   sa_len(&forward->sentto->addr))));
          
          return 1;
        }
@@ -469,14 +465,12 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
 #endif
                }
              
-             if (sendto(fd, (char *)header, plen, 0,
-                        &start->addr.sa,
-                        sa_len(&start->addr)) == -1)
-               {
-                 if (retry_send())
-                   continue;
-               }
-             else
+             if (retry_send(sendto(fd, (char *)header, plen, 0,
+                                   &start->addr.sa,
+                                   sa_len(&start->addr))))
+               continue;
+           
+             if (errno == 0)
                {
                  /* Keep info in case we want to re-send this packet */
                  daemon->srv_save = start;
@@ -932,7 +926,9 @@ void reply_query(int fd, int family, time_t now)
                  
                  if (fd != -1)
                    {
-                     while (sendto(fd, (char *)header, nn, 0, &server->addr.sa, sa_len(&server->addr)) == -1 && retry_send()); 
+                     while (retry_send(sendto(fd, (char *)header, nn, 0, 
+                                              &server->addr.sa, 
+                                              sa_len(&server->addr)))); 
                      server->queries++;
                    }
                  
@@ -2228,8 +2224,9 @@ void resend_query()
       else
        return;
       
-      while(sendto(fd, daemon->packet, daemon->packet_len, 0,
-                  &daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send()); 
+      while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
+                             &daemon->srv_save->addr.sa, 
+                             sa_len(&daemon->srv_save->addr)))); 
     }
 }
 
index 8c5b727223710585449912bb9b33f5bc6c2ae680..a315e86bc7f49f9f441f4d0266d3b72982b98d0c 100644 (file)
@@ -121,7 +121,6 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
   struct my_nlattr *nested[2];
   uint8_t proto;
   int addrsz = INADDRSZ;
-  ssize_t rc;
 
 #ifdef HAVE_IPV6
   if (af == AF_INET6)
@@ -162,9 +161,10 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
   nested[1]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[1];
   nested[0]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[0];
        
-  while ((rc = sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
-                     (struct sockaddr *)&snl, sizeof(snl))) == -1 && retry_send());
-  return rc;
+  while (retry_send(sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
+                          (struct sockaddr *)&snl, sizeof(snl))));
+                                                                   
+  return errno == 0 ? 0 : -1;
 }
 
 
index 565f7d8e58e06a3c23ce6fe899173bcf64fef3c1..c9ed075670de12e2eeb765b0dba0b04f4e60f04d 100644 (file)
@@ -45,8 +45,9 @@ void loop_send_probes()
             fd = rfd->fd;
           }
 
-        while (sendto(fd, daemon->packet, len, 0, &serv->addr.sa, sa_len(&serv->addr)) == -1 && retry_send());
-
+        while (retry_send(sendto(fd, daemon->packet, len, 0, 
+                                 &serv->addr.sa, sa_len(&serv->addr))));
+        
         free_rfd(rfd);
        }
 }
index 10f94db25a14be8ece73151110afa9b168abd311..753784dc20b44f83529b3c0eae472c280433fc71 100644 (file)
@@ -169,10 +169,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
   req.g.rtgen_family = family; 
 
   /* Don't block in recvfrom if send fails */
-  while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0, 
-                     (struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());
-  
-  if (len == -1)
+  while(retry_send(sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0, 
+                         (struct sockaddr *)&addr, sizeof(addr))));
+
+  if (errno != 0)
     return 0;
     
   while (1)
index 6da125b864ae9602585efd7f31e19c5c4e65f677..d0faddf8684a0e7792fe2387cb3d82557c40eb49 100644 (file)
@@ -479,8 +479,9 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
       setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(iface));
     }
   
-  while (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0, 
-               (struct sockaddr *)&addr, sizeof(addr)) == -1 && retry_send());
+  while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base, 
+                          save_counter(0), 0, (struct sockaddr *)&addr, 
+                          sizeof(addr))));
   
 }
 
index 91d02410b13ff5e08e9275bfdd972b01bfba28b1..648bc4d4b4283cef8e4fb8df7d82dcf739d65b3e 100644 (file)
@@ -569,17 +569,27 @@ void bump_maxfd(int fd, int *max)
     *max = fd;
 }
 
-int retry_send(void)
+/* rc is return from sendto and friends.
+   Return 1 if we should retry.
+   Set errno to zero if we succeeded. */
+int retry_send(ssize_t rc)
 {
+  static int retries = 0;
+  struct timespec waiter;
+  
+  if (rc != -1)
+    {
+      retries = 0;
+      errno = 0;
+      return 0;
+    }
+  
   /* 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)
+  if (errno == EAGAIN || errno == EWOULDBLOCK)
      {
        waiter.tv_sec = 0;
        waiter.tv_nsec = 10000;
@@ -587,13 +597,13 @@ int retry_send(void)
        if (retries++ < 1000)
         return 1;
      }
-
-   retries = 0;
-   
-   if (errno == EINTR)
-     return 1;
-   
-   return 0;
+  
+  retries = 0;
+  
+  if (errno == EINTR)
+    return 1;
+  
+  return 0;
 }
 
 int read_write(int fd, unsigned char *packet, int size, int rw)
@@ -602,22 +612,21 @@ int read_write(int fd, unsigned char *packet, int size, int rw)
   
   for (done = 0; done < size; done += n)
     {
-    retry:
-      if (rw)
-        n = read(fd, &packet[done], (size_t)(size - done));
-      else
-        n = write(fd, &packet[done], (size_t)(size - done));
-
-      if (n == 0)
-        return 0;
-      else if (n == -1)
-        {
-          if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
-            goto retry;
-          else
-            return 0;
-        }
+      do { 
+       if (rw)
+         n = read(fd, &packet[done], (size_t)(size - done));
+       else
+         n = write(fd, &packet[done], (size_t)(size - done));
+       
+       if (n == 0)
+         return 0;
+       
+      } while (retry_send(n) || errno == ENOMEM || errno == ENOBUFS);
+
+      if (errno != 0)
+       return 0;
     }
+     
   return 1;
 }