]> git.ipfire.org Git - thirdparty/man-pages.git/commitdiff
dup.2: Fix erroneous discussion regarding closing 'newfd' before calling dup2()
authorMichael Kerrisk <mtk.manpages@gmail.com>
Fri, 30 May 2014 09:12:13 +0000 (11:12 +0200)
committerMichael Kerrisk <mtk.manpages@gmail.com>
Sun, 29 Jun 2014 07:49:08 +0000 (09:49 +0200)
And propose a workaround if the caller cares about catching
close() time errors.

See http://stackoverflow.com/questions/23440216/race-condition-when-using-dup2#comment36888604_23444465
and http://austingroupbugs.net/view.php?id=411

Reported-by: Rich Felker <dalias@libc.org>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
man2/dup.2

index fc02112360b95760f89685e225e54f9fe1e8622a..70b6f4ea97d8c00bb04668b59a50cb0487be529b 100644 (file)
@@ -225,13 +225,42 @@ If
 was open, any errors that would have been reported at
 .BR close (2)
 time are lost.
-A careful programmer will not use
-.BR dup2 ()
-or
-.BR dup3 ()
-without closing
+If this is of concern,
+then\(emunless the program is single-threaded and does not allocate
+file descriptors in signal handlers\(emthe correct approach is
+.I not
+to close
 .I newfd
-first.
+before calling
+.BR dup2 (),
+because of the race condition described above.
+Instead, code something like the following could be used:
+
+.nf
+    /* Obtain a duplicate of 'newfd' that can subsequently
+       be used to check for close() errors; an EBADF error
+       means that 'newfd' was not open. */
+
+    tmpfd = dup(newfd);
+    if (tmpfd == \-1 && errno != EBADF) {
+        /* Handle unexpected dup() error */
+    }
+
+    /* Atomically duplicate 'oldfd' on 'newfd' */
+
+    if (dup2(oldfd, newfd) == \-1) {
+        /* Handle dup2() error */
+    }
+
+    /* Now check for close() errors on the file originally
+       referred to by 'newfd' */
+
+    if (tmpfd != \-1) {
+        if (close(tmpfd) == \-1) {
+            /* Handle errors from close */
+        }
+    }
+.fi
 .SH SEE ALSO
 .BR close (2),
 .BR fcntl (2),