summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Kerrisk <mtk.manpages@gmail.com>2014-05-30 11:12:13 +0200
committerMichael Kerrisk <mtk.manpages@gmail.com>2014-06-29 09:49:08 +0200
commit422bb2b4ecec1d16858e4871db39a0bc384987a2 (patch)
tree0473cfd6d7e4fab3b55d47d57e6114e98800ed96
parent44505a6fdcc716e58684c3c28c477fb7e657098a (diff)
dup.2: Fix erroneous discussion regarding closing 'newfd' before calling dup2()
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>
-rw-r--r--man2/dup.241
1 files changed, 35 insertions, 6 deletions
diff --git a/man2/dup.2 b/man2/dup.2
index fc0211236..70b6f4ea9 100644
--- a/man2/dup.2
+++ b/man2/dup.2
@@ -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),