safeio: ignore EINTR on close()
authorMarko Kreen <markokr@gmail.com>
Thu, 5 Apr 2012 13:26:05 +0000 (16:26 +0300)
committerMarko Kreen <markokr@gmail.com>
Thu, 5 Apr 2012 13:31:44 +0000 (16:31 +0300)
Seems the retry is dangerous at least on Linux, BSDs and Solaris.

This should be enough to prove it's not good idea.

usual/safeio.c

index 08595f0e6ba9c033b4c4f1a83d71a479f660cde8..9362dc83fc6b9f28411a7471493040600515d67e 100644 (file)
@@ -83,18 +83,34 @@ loop:
 int safe_close(int fd)
 {
        int res;
-loop:
-       /* by manpage, the close() could be interruptable
-          although it seems that at least in linux it cannot happen */
+
 #ifndef WIN32
+       /*
+        * POSIX says close() can return EINTR but fd state is "undefined"
+        * later.  Seems Linux and BSDs close the fd anyway and EINTR is
+        * simply informative.  Thus retry is dangerous.
+        */
        res = close(fd);
 #else
-       /* Pending(this is necessary to wait for FIN of a client.) */
-       log_debug("closesocket(%d)",fd);
+       /*
+        * Seems on windows it can returns proper EINTR but only when
+        * WSACancelBlockingCall() is called.  As we don't do it,
+        * ignore EINTR on win32 too.
+        */
        res = closesocket(fd);
 #endif
+       if (res < 0) {
+               char ebuf[128];
+               log_warning("safe_close(%d) = %s", fd,
+                           strerror_r(errno, ebuf, sizeof(ebuf)));
+       } else if (cf_verbose > 2) {
+               log_noise("safe_close(%d) = %d", fd, res);
+       }
+
+       /* ignore EINTR */
        if (res < 0 && errno == EINTR)
-               goto loop;
+               return 0;
+
        return res;
 }