From dean@arctic.org Sat Nov 25 23:31:36 2006
Date: Sat, 25 Nov 2006 23:31:36 -0800 (PST)
From: dean gaudet <dean@arctic.org>
To: bugs@ucarp.org
Subject: [patch] handle EINTR in various places in ucarp

when i strace ucarp it exits because it isn't ready to handle EINTR in 
several places.  the critical one is the poll() case, but i scanned the 
code and found a handful of other syscalls which should handle EINTR as 
well.

note that in several cases i really do think we should log errors -- 
especially in the cases which cause ucarp to exit (i.e. the poll errors).  
i've made several adjustments in that respect.

the only part of this patch i didn't test directly was the wait3 change.

let me know what you think...

thanks
-dean


Index: ucarp-1.2/src/carp.c
===================================================================
--- ucarp-1.2.orig/src/carp.c	2006-11-25 23:00:55.000000000 -0800
+++ ucarp-1.2/src/carp.c	2006-11-25 23:10:48.000000000 -0800
@@ -185,6 +185,7 @@
     size_t eth_len;
     int advbase;
     int advskew;
+    int rc;
 
 #ifdef DEBUG
     logfile(LOG_DEBUG, "-> carp_send_ad()");
@@ -260,11 +261,12 @@
     sum = cksum(ip_ptr, ip_len);
     ip_ptr[offsetof(struct ip, ip_sum)] = (sum >> 8) & 0xff;
     ip_ptr[offsetof(struct ip, ip_sum) + 1] = sum & 0xff;
-        
-    if (write(dev_desc_fd, pkt, eth_len) < 0) {
-#ifdef DEBUG
-        logfile(LOG_WARNING, _("write() has failed"));
-#endif
+
+    do {
+	rc = write(dev_desc_fd, pkt, eth_len);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        logfile(LOG_WARNING, _("write() has failed: %s"), strerror(errno));
         if (sc->sc_sendad_errors < INT_MAX) {
             sc->sc_sendad_errors++;
         }
@@ -705,11 +707,13 @@
     
     for (;;) {
         nfds = poll(pfds, (nfds_t) 1, sc.sc_advbase * 1000);
-        if (nfds == -1 || 
-            (pfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) != 0) {
-#ifdef DEBUG
-            logfile(LOG_NOTICE, "poll() error");
-#endif
+	if (nfds == -1) {
+	    if (errno == EINTR) continue;
+	    logfile(LOG_ERR, _("exiting: poll() error: %s"), strerror(errno));
+	    break;
+	}
+        if ((pfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) != 0) {
+            logfile(LOG_ERR, _("exiting: pfds[0].revents = %d"), pfds[0].revents);
             break;
         }
         if (gettimeofday(&now, NULL) != 0) {
Index: ucarp-1.2/src/garp.c
===================================================================
--- ucarp-1.2.orig/src/garp.c	2006-11-25 23:14:04.000000000 -0800
+++ ucarp-1.2/src/garp.c	2006-11-25 23:15:12.000000000 -0800
@@ -21,6 +21,7 @@
     };    
     unsigned char *pkt;
     struct ether_header *eh_ptr;
+    int rc;
 
     memcpy(&arp[8], hwaddr, sizeof hwaddr);    
     if (enable_virtual == 0) {
@@ -46,10 +47,11 @@
         eh.ether_type = htons(ETHERTYPE_ARP);
         memcpy(pkt, &eh, sizeof eh);
     }
-    if (write(dev_desc_fd, pkt, sizeof *eh_ptr + sizeof arp) < 0) {
-#ifdef DEBUG
-        logfile(LOG_DEBUG, "write() in garp: %s", strerror(errno));
-#endif
+    do {
+	rc = write(dev_desc_fd, pkt, sizeof *eh_ptr + sizeof arp);
+    } while (rc < 0 && errno == EINTR);
+    if (rc < 0) {
+        logfile(LOG_ERR, _("write() in garp: %s"), strerror(errno));
         ALLOCA_FREE(pkt);
         return -1;
     }
Index: ucarp-1.2/src/spawn.c
===================================================================
--- ucarp-1.2.orig/src/spawn.c	2006-11-25 23:17:48.000000000 -0800
+++ ucarp-1.2/src/spawn.c	2006-11-25 23:21:57.000000000 -0800
@@ -25,13 +25,19 @@
     } else if (pid != (pid_t) -1) {
         logfile(LOG_WARNING, _("Spawning [%s %s]"), script, interface);
 #ifdef HAVE_WAITPID
-        (void) waitpid(pid, NULL, 0);
+	{
+	    while (waitpid(pid, NULL, 0) == (pid_t) -1 && errno == EINTR) {
+		;
+	    }
+	}
 #else
         {
             pid_t foundpid;
             
-            while ((foundpid = wait3(NULL, 0, NULL)) != (pid_t) -1 &&
-                   foundpid != pid);
+	    do {
+		foundpid = wait3(NULL, 0, NULL);
+		if (foundpid == (pid_t) -1 && errno == EINTR) continue;
+	    } while (foundpid != (pid_t) -1 && foundpid != pid);
         }
 #endif
     } else {
