Calling close(fileno(fp)) prior to fclose(fp) is racy in a
multi-threaded application - some other thread could open a new file,
which is then inadvertently closed by the fclose that we thought
should fail with EBADF. For mingw, this is no worse than the race
already present in close_fd_maybe_socket for calling closesocket()
prior to _close(), but for all other platforms, we might as well be
nice and avoid the race.
* lib/fclose.c (rpl_fclose): Rewrite to avoid double-close race on
all but WINDOWS_SOCKETS.
Signed-off-by: Eric Blake <eblake@redhat.com>
+2011-05-10 Eric Blake <eblake@redhat.com>
+
+ fclose: avoid double close race when possible
+ * lib/fclose.c (rpl_fclose): Rewrite to avoid double-close race on
+ all but WINDOWS_SOCKETS.
+
2011-05-10 Bastien Roucariès <roucaries.bastien@gmail.com>
openat: correct new comment
{
int saved_errno = 0;
int fd;
+ int result = 0;
/* Don't change behavior on memstreams. */
fd = fileno (fp);
&& fflush (fp))
saved_errno = errno;
+#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. */
if (close (fd) < 0 && saved_errno == 0)
saved_errno = errno;
- fclose (fp); /* will fail with errno = EBADF */
+ fclose (fp); /* will fail with errno = EBADF, if we did not lose a race */
if (saved_errno != 0)
{
errno = saved_errno;
- return EOF;
+ result = EOF;
}
- return 0;
+
+#else /* !WINDOWS_SOCKETS */
+ /* No race here. */
+ result = fclose (fp);
+
+# if REPLACE_FCHDIR
+ if (result == 0)
+ unregister_shadow_fd (fd);
+# endif
+#endif /* !WINDOWS_SOCKETS */
+
+ return result;
}