]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/util/socket.c
Merge sf
[netatalk.git] / libatalk / util / socket.c
index 9edeb6c55c0cf34f380c121b77826a43d7c71972..fe42cd76453c7ca9649817c344e2e9a5b0f82740 100644 (file)
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 600
-#endif
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__
-#endif
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
+#if !defined(__FreeBSD__)
+# ifndef _XOPEN_SOURCE
+#  define _XOPEN_SOURCE 600
+# endif
+# ifndef __EXTENSIONS__
+#  define __EXTENSIONS__
+# endif
+# ifndef _GNU_SOURCE
+#  define _GNU_SOURCE
+# endif
 #endif
 #include <unistd.h>
 #include <fcntl.h>
@@ -87,7 +89,7 @@ int setnonblock(int fd, int cmd)
  *                             io mode for the socket
  * @param timeout         (r)  number of seconds to try reading
  *
- * @returns number of bytes actually read or -1 on fatal error
+ * @returns number of bytes actually read or -1 on timeout or error
  */
 ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, int timeout)
 {
@@ -97,6 +99,8 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
     fd_set rfds;
     int ret;
 
+    FD_ZERO(&rfds);
+
     if (setnonblocking) {
         if (setnonblock(socket, 1) != 0)
             return -1;
@@ -114,7 +118,6 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
             case EINTR:
                 continue;
             case EAGAIN:
-                FD_ZERO(&rfds);
                 FD_SET(socket, &rfds);
                 tv.tv_usec = 0;
                 tv.tv_sec  = timeout;
@@ -122,14 +125,16 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
                 while ((ret = select(socket + 1, &rfds, NULL, NULL, &tv)) < 1) {
                     switch (ret) {
                     case 0:
-                        LOG(log_warning, logtype_afpd, "select timeout %d s", timeout);
+                        LOG(log_debug, logtype_afpd, "select timeout %d s", timeout);
+                        errno = EAGAIN;
                         goto exit;
 
                     default: /* -1 */
-                        if (errno == EINTR) {
+                        switch (errno) {
+                        case EINTR:
                             (void)gettimeofday(&now, NULL);
                             if (now.tv_sec >= end.tv_sec && now.tv_usec >= end.tv_usec) {
-                                LOG(log_warning, logtype_afpd, "select timeout %d s", timeout);
+                                LOG(log_debug, logtype_afpd, "select timeout %d s", timeout);
                                 goto exit;
                             }
                             if (now.tv_usec > end.tv_usec) {
@@ -139,13 +144,18 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
                                 tv.tv_usec = end.tv_usec - now.tv_usec;
                                 tv.tv_sec  = end.tv_sec - now.tv_sec;
                             }
-                            FD_ZERO(&rfds);
                             FD_SET(socket, &rfds);
                             continue;
+                        case EBADF:
+                            /* possibly entered disconnected state, don't spam log here */
+                            LOG(log_debug, logtype_afpd, "select: %s", strerror(errno));
+                            stored = -1;
+                            goto exit;
+                        default:
+                            LOG(log_error, logtype_afpd, "select: %s", strerror(errno));
+                            stored = -1;
+                            goto exit;
                         }
-                        LOG(log_error, logtype_afpd, "select: %s", strerror(errno));
-                        stored = -1;
-                        goto exit;
                     }
                 } /* while (select) */
                 continue;
@@ -485,7 +495,8 @@ void fdset_add_fd(struct pollfd **fdsetp,
  * Remove a fd from our pollfd array
  *
  * 1. Search fd
- * 2. If we remove the last array elemnt, just decrease count
+ * 2a 
+ * 2b If we remove the last array elemnt, just decrease count
  * 3. If found move all following elements down by one
  * 4. Decrease count of used elements in array
  *
@@ -506,9 +517,15 @@ void fdset_del_fd(struct pollfd **fdsetp,
     struct pollfd *fdset = *fdsetp;
     struct polldata *polldata = *polldatap;
 
+    if (*fdset_usedp < 1)
+        return;
+
     for (int i = 0; i < *fdset_usedp; i++) {
         if (fdset[i].fd == fd) { /* 1 */
-            if (i < (*fdset_usedp - 1)) { /* 2 */
+            if (i == 0 && *fdset_usedp == 1) { /* 2a */
+                fdset[i].fd = -1;
+                memset(&polldata[i], 0, sizeof(struct polldata));
+            } else if (i < (*fdset_usedp - 1)) { /* 2b */
                 memmove(&fdset[i], &fdset[i+1], (*fdset_usedp - 1) * sizeof(struct pollfd)); /* 3 */
                 memmove(&polldata[i], &polldata[i+1], (*fdset_usedp - 1) * sizeof(struct polldata)); /* 3 */
             }