dup2

Root Boy Jim rbj at uunet.UU.NET
Fri Feb 15 15:16:42 AEST 1991


richard at locus.com (Richard M. Mathews) writes:
? rbj at uunet.UU.NET (Root Boy Jim) writes:
? >richard at locus.com (Richard M. Mathews) writes:
? >>I have not yet seen a correct version of code for dup2() posted.  The
? >>versions posted by Paul Falsted, Doug Gwyn, and Root Boy Jim all fail
? >>the following test case because they close "fd2" too soon:

? >I suppose it depends on your interpretation.

And my interpretation was from the manual page. Remember, I am
not writing Posix library code, or a Gwynix emulation package,
but something I can plug into a piece of code that I'm trying
to compile on a system that may not have dup2.

? >If you try dup2(-1,fileno(stdout))
? >and end up with nowhere to print to, have you not made a copy of your
? >input file descriptor?
?
? By your argument, dup2(-1,fd) should be
? equivalent to close(fd) and should return success if the close succeeds. 

Sure, why not? I have made a copy of what you gave me.
With lemons, I make lemonade. Garbage in, garbage out. 

And close always succeeds. Or rather, the only way it can fail is
by attempting to close something which is not open. In any case,
it's closed after the call.
 
? >What does the shell do with "cmd >&- 2>&1"?

? The above mentioned code returns without touching fd2 if the getf()
? fails on fd1.  

You're right, it complains. Sorry, not a good example. Or is it?
Shouldn't I be able to close stderr that way? The answer is debatable.

? It certainly makes sense that if you return -1 you should
? leave the state of the process unchanged.

Interesting notion. I'm not sure it's possible, tho, especially
in a system call with complex interactions.

? This clearly is not the way dup2 is documented (it says, "-1
? is returned if the given file descriptor is invalid").

Regarding dup2, you can't use "clearly" and "documented" in the
same sentence. Even the SunOS manual pages, which are more
specific than earlier manuals, are rather nebulous about the exact
sequence. You deserve what you get.

? >And what is the "meaning" of dup2(1,1)? Anyone who trys to do this
? >probably has a logic error somewhere, regardless of the definition.
? >In any case, I am willing to add "if (new == old) return(new);" to my code.
? 
? The above mentioned code has a special case to make sure it treats this
? as a no-op (though it does validate fd1).

That is the meaning, but what is the "meaning"? I claim that anyone
who calls dup2 with identical arguments has made a logic error.
Often, dup2(old,new) is followed by close(old). The end result
is the same. Perhaps a better solution would be to simply return
an error while leaving the identical descriptor alone.

? >I also claim that I handled errno properly. It is not necessary
? >to preserve the old value of errno if dup2 returns true.
? 
? The above mentioned code uses EBADF.  Fcntl uses EINVAL.  You definitely
? got that errno wrong. 

Touche. I threw the fcntl part in at the last minute.

This has turned into a rather dry discussion on minutiae, which
obscures the beauty of the recursive solution. To be honest, I
didn't write it, altho I did fix the implementation.

Or rather, I did the 20% of the code that solves 80% of the cases.
Most people don't even check dup or dup2 because they "always work".
At least I made the attempt. The objections you bring up are
rather gray areas. To my mind, it's not clear that the standard
definition is truly optimal, or that it applies all that often.

? As for preserving errno on success, it certainly
? is true that V7 dup2 did do so

Because it was done in the kernel, where you have to go out
of your way to alter a variable in user space.
And it was done directly, rather than glommed onto something else.

? but it isn't clear that you need to.

Exactly.

? The manual says in intro(2) that, "Errno is not cleared on successful
? calls."  It doesn't promise that errno isn't changed.  I think it is a
? nice extra feature to add those few lines of code to preserve errno.

I believe the fcntl errno should be remapped correctly.

On preserving the previous errno upon successful return,
I disagree. In fact I believe it is actually counterproductive. 

As more and more "system calls" are replaced with
library functions to more general, powerful and modern interfaces,
this task gets harder and harder, all for dubious results. 

And some day someone will complain when errno changes mysteriously.
Better to declare open season on it now before people start caring.

If you didn't test it immediately, then you didn't really
care about it and it's gone forever.

However, I thank you for your observations. It's refreshing to know
that the man who smugly wrote "We think of everything" didn't.

? Richard M. Mathews			 Freedom for Lithuania
? richard at locus.com				Laisve!
? lcc!richard at seas.ucla.edu
? ...!{uunet|ucla-se|turnkey}!lcc!richard
-- 
		[rbj at uunet 1] stty sane
		unknown mode: sane



More information about the Comp.unix.internals mailing list