changeset 14726:3e7ea0014c67

fclose: Fix possible link error. * lib/fclose.c (rpl_fclose): Invoke _gl_unregister_fd, not unregister_shadow_fd. Improve comments. * lib/sockets.c (close_fd_maybe_socket): Add comments. Reported by Eric Blake.
author Bruno Haible <bruno@clisp.org>
date Wed, 11 May 2011 13:14:46 +0200
parents d27620fb3331
children a031482490fc
files ChangeLog lib/fclose.c lib/sockets.c
diffstat 3 files changed, 28 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-05-11  Bruno Haible  <bruno@clisp.org>
+
+	fclose: Fix possible link error.
+	* lib/fclose.c (rpl_fclose): Invoke _gl_unregister_fd, not
+	unregister_shadow_fd. Improve comments.
+	* lib/sockets.c (close_fd_maybe_socket): Add comments. Reported by
+	Eric Blake.
+
 2011-05-11  Jim Meyering  <meyering@redhat.com>
 
 	maint.mk: improve "can not" detection and generalize rule name
--- a/lib/fclose.c
+++ b/lib/fclose.c
@@ -46,10 +46,12 @@
       && fflush (fp))
     saved_errno = errno;
 
+  /* fclose() calls close(), but we need to also invoke all hooks that our
+     overridden close() function invokes.  See lib/close.c.  */
 #if WINDOWS_SOCKETS
-  /* There is a minor race where some other thread could open fd
-     between our close and fopen, but it is no worse than the race in
-     close_fd_maybe_socket.  */
+  /* Call the overridden close(), then the original fclose().
+     Note about multithread-safety: There is a race condition where some
+     other thread could open fd between our close and fclose.  */
   if (close (fd) < 0 && saved_errno == 0)
     saved_errno = errno;
 
@@ -62,13 +64,20 @@
     }
 
 #else /* !WINDOWS_SOCKETS */
-  /* No race here.  */
-  result = fclose (fp);
+  /* Call fclose() and invoke all hooks of the overridden close().  */
 
 # if REPLACE_FCHDIR
-  if (result == 0)
-    unregister_shadow_fd (fd);
+  /* Note about multithread-safety: There is a race condition here as well.
+     Some other thread could open fd between our calls to fclose and
+     _gl_unregister_fd.  */
+  result = fclose (fp);
+  if (result >= 0)
+    _gl_unregister_fd (fd);
+# else
+  /* No race condition here.  */
+  result = fclose (fp);
 # endif
+
 #endif /* !WINDOWS_SOCKETS */
 
   return result;
--- a/lib/sockets.c
+++ b/lib/sockets.c
@@ -37,6 +37,10 @@
                        gl_close_fn primary,
                        int fd)
 {
+  /* Note about multithread-safety: There is a race condition where, between
+     our calls to closesocket() and the primary close(), some other thread
+     could make system calls that allocate precisely the same HANDLE value
+     as sock; then the primary close() would call CloseHandle() on it.  */
   SOCKET sock;
   WSANETWORKEVENTS ev;