diff options
author | Michael Kerrisk <mtk.manpages@gmail.com> | 2014-05-30 11:12:13 +0200 |
---|---|---|
committer | Michael Kerrisk <mtk.manpages@gmail.com> | 2014-06-29 09:49:08 +0200 |
commit | 422bb2b4ecec1d16858e4871db39a0bc384987a2 (patch) | |
tree | 0473cfd6d7e4fab3b55d47d57e6114e98800ed96 | |
parent | 44505a6fdcc716e58684c3c28c477fb7e657098a (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.2 | 41 |
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), |