Subject: Re: bug#8846: coreutils-8.12 on HP-UX 11.31: 3 of 365 tests failed

From: Eric Blake <[email-masked]>
Date: Mon, 13 Jun 2011 16:38:07 -0600

On 06/13/2011 04:24 PM, Stefano Lattarini wrote:
> On Monday 13 June 2011, Eric Blake wrote:
>>
>> Not possible to portably sniff out closed fds; quoting the autoconf manual:
>>
>>> Don't rely on duplicating a closed file descriptor to cause an
>>> error.  With Solaris @command{/bin/sh}, when the redirection fails, the
>>> output goes to the original file descriptor.
>>
> Do the shells with the close-on-exec issue also suffer of the issue with
> closed fds you've reported?  If not, the following could be enough to
> solve our situation without having to change automake:

Where are you proposing this hack?  In init.sh (after fd 9 has already
been closed if the calling shell used exec instead of some other form of
redirection)?  That is, why are we trying to fix init.sh to deal with a
closed fd after the fact, when it seems like the better approach is to
guarantee that fd is never closed on exec in the first place?  Which
necessarily implies altering the caller.

> 
>   if (exec 3>&-; exec 4>&3) >/dev/null 2>&1; then
>     # Cannot determine whether a file descriptor is closed, fall back
>     # to inferior hack.
>     if test 2 -ne "$stderr_fileno_" && test ! -t "$stderr_fileno_"; then
>       eval "exec $stderr_fileno_>&2" # Or is `stderr_fileno_=2' enough?
>     fi

Or is the whole point of this hack to init.sh to avoid the spurious
warning about EBADF and to instead redirect errors to the
(possibly-altered-by-make) fd 2 when fd 9 was lost, so that at least the
warning messages appear in the logs even though we lost the chance to
display them on the tty?

At any rate, in answer to your question:

Solaris /bin/sh (the shell where failed redirections are silently
ignored) does this:

$ /bin/sh -c '(exec 3>&-; exec 4>&3) >/dev/null 2>&1; echo $?'
0
$ cat k
#!/bin/sh
e=9; warn_ () { echo "$@" 1>&$e; }; warn_ x
$ /bin/sh k
x
$ /bin/sh k >/dev/null
$ /bin/sh k 9>&2
x
$ /bin/sh k 9>&2 >/dev/null
x

That is, if fd 9 is closed, then 1>&$e (aka >&9) is a no-op on that
shell, and output goes to the original fd 1; but if fd 9 is open, then
output goes to fd 9.

Whereas ksh and HP-UX sh are both vocal on failed redirections, for
reliable detection:

$ ksh -c '(exec 3>&-; exec 4>&3) >/dev/null 2>&1; echo $?'
1
$ ksh k
k[2]: 9: cannot open [Bad file number]
$ ksh k >/dev/null
k[2]: 9: cannot open [Bad file number]
$ ksh k 9>&2
x
$ ksh k 9>&2 >/dev/null
x

-- 
Eric Blake   [email-masked]    +1-801-349-2682
Libvirt virtualization library http://libvirt.org