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>
This commit is contained in:
Michael Kerrisk 2014-05-30 11:12:13 +02:00
parent 44505a6fdc
commit 422bb2b4ec
1 changed files with 35 additions and 6 deletions

View 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),