Post by Michael KerriskPost by Geoff ClarePost by Casper.Dik-QHcLZuEGTsvQT0dZR+Post by Geoff ClareInteresting point. I think the only reasonable interpretation of
"the [two] lowest available descriptor(s)" is that when two threads
call pipe() (or open() or whatever) at the same time, the competition
for the lowest file descriptor(s) is "won" by one of them and the
winner is treated as as if it was called before the loser. Perhaps
we should add some words to that effect (but more formal) somewhere.
But should the standard be written such that returning 3 & 4 and 5 & 6 is
the only valid outcome?
I'd suggest that 3 & 5 and 4 & 6 as well as 3 & 6 and 4 & 5 should be
equally valid.
It makes little sense to force a lock on "get a new file descriptor"
during a part of the call of pipe() when new file descriptors are
allocated.
In Solaris, it seems that all possible outcomes listed here look possible.
I see no reason why the standard should insist on a single-threaded view
of the world in those cases were a program cannot reliably detect whether
the standard is being followed or not.
This was discussed in yesterday's teleconference and the consensus was
in agreement with your views here. I.e. each individual fd allocation
should be atomic and there should be no requirement for pipe() to
allocate both fds in one atomic operation.
I wonder if things are so straightforward. The following point came up
in a conversation I had this week.
There's a lot of code out there that has sequences like this to set
stdout to be the write end of a pipe (or analogously, stdin to be the
int pfd[2];
pipe(pfd);
if (pfd[1] != STDOUT_FILENO) { /* Defensive check */
dup2(pfd[1], STDOUT_FILENO);
close(pfd[1]);
}
If file descriptors 0 and 1 are closed before the call to pipe(), then
the above sequence is broken if pipe() returns the file descriptors in
unnatural order--that is, 1 in pfd[0] and 0 in pfd[1], since we end up
doing the following
dup2(0, 1); /* Close FD 0, duplicate it on FD 1 */
close(0); /* No-op */
Should be:
dup2(0, 1); /* Close FD 1, duplicate FD 0 on FD 1 */
close(0); /* Close FD 0 */
Post by Michael KerriskIs it really meant that POSIX is saying that all of the existing code
that follows the above pattern is broken, or is there perhaps some
other point in the standard that I am missing?
While I agree that code like the above is common, I'm doubtful that
it is ever used with fds 0 and 1 both closed. The usual situation
where a pipe is set up with fds 0 and 1 as its read and write ends
is to connect two processes so that one reads the output of the other.
The first process has the write end as fd 1; the second has the read
end as fd 0; there is no process that has the two ends of the pipe
on fd 0 and fd 1, so closing them before calling pipe() seems like a
very odd thing to do. Can you point to any real code that actually
does that?
I suppose if we do want to cater to applications that do it, then all
the standard would need to do is require that pipe() allocates pfd[0]
before it allocates pfd[1]. In a single-threaded process with no
signal handlers that manipulate file descriptors, this would
guarantee that closing fds 0 and 1 before calling pipe() puts 0 in
pfd[0] and 1 in pfd[1].
--
Geoff Clare <g.clare-7882/***@public.gmane.org>
The Open Group, Apex Plaza, Forbury Road, Reading, RG1 1AX, England