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

From: Jim Meyering <[email-masked]>
Date: Mon, 13 Jun 2011 19:01:02 +0200

Eric Blake wrote:

> On 06/13/2011 09:37 AM, Jim Meyering wrote:
>>> But I think the reason that it invokes a problem is not because of the
>>> 1>&$e construct, but because HP-UX opens secondary file descriptors as
>>> cloexec or otherwise closing them at some point, so the '/bin/sh k'
>>> child process is not inheriting fd 9 from the parent process.
>>
>> Ah ha!
>> That sounds like a syscall that needs to be gnulib-replaced in bash/zsh.
>> Of course, first we'd need to gnulib-enable a shell.
>
> Yep, I've confirmed that both HP-UX and Solaris 10 ksh use CLOEXEC fds
> for intermediate fd values created by exec; that POSIX permits (but
> fortunately does not require) this behavior, and that autoconf already
> documents the pitfall of expecting fds > 2 to be preserved into child
> processes:
>
> http://www.gnu.org/software/autoconf/manual/autoconf.html#File-Descriptors
>
>> Don't rely on open file descriptors being open in child
>> processes. In ksh, file descriptors above 2 which are opened using
>> ‘exec n>file’ are closed by a subsequent ‘exec’ (such as that
>> involved in the fork-and-exec which runs a program or script). Thus,
>> using sh, we have:
>>
>>      $ cat ./descrips
>>      #!/bin/sh -
>>      echo hello >&5
>>      $ exec 5>t
>>      $ ./descrips
>>      $ cat t
>>      hello
>>      $
>>
>> But using ksh:
>>
>>      $ exec 5>t
>>      $ ./descrips
>>      hello
>>      $ cat t
>>      $
>
> On Solaris 10, truss shows this for 'exec 9>&2':
>
> dup(2)                                          = 3
> close(9)                                        Err#9 EBADF
> fcntl(3, F_DUPFD, 0x00000009)                   = 9
> close(3)                                        = 0
> fcntl(9, F_SETFD, 0x00000001)                   = 0
>
>>   tusc (11+, freeware)
>
> Likewise on HP-UX 11.31, tusc shows:
>
> dup(2) ................................................... = 3
> close(9) ................................................. ERR#9 EBADF
> fcntl(3, F_DUPFD, 9) ..................................... = 9
> close(3) ................................................. = 0
> fcntl(9, F_SETFD, 1) ..................................... = 0
>
> About the only thing I can think of is to pass the details about the
> desired redirection as a command-line or env-var setting, to be done by
> the script itself, rather than relying on the parent shell (the one in
> make) being able to do a redirection that persists into the child (the
> one sourcing init.sh).

Thanks for confirming.
Actually the fix (at least for bourne shell scripts) is even easier
than that: perform the redirection from init.sh's setup_ function

I'm going to revert (in coreutils) my eval-adding change,
and then apply this instead:

>From d987cf87de5e7e597e295914c536bd332c24cc63 Mon Sep 17 00:00:00 2001
From: Jim Meyering <[email-masked]>
Date: Mon, 13 Jun 2011 18:54:53 +0200
Subject: [PATCH] init.sh: redirect FD 9 to stderr again, for Solaris 10 and
 HP-UX

* tests/init.sh (setup_): When $stderr_fileno_ is not 2, redirect it.
Prior to this change, we would redirect before the shell fork-and-exec
performed via automake's TESTS_ENVIRONMENT, but that redirection was
ineffective on Solaris 10 and HP-UX 11.31, due to the fact that those
systems set the CLOEXEC bit on FDs larger than 2.  Thus our redirection
of FD 9 would not survive the fork-and-exec of running each test script.
---
 tests/init.sh |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/tests/init.sh b/tests/init.sh
index 60d1bc1..d101643 100644
--- a/tests/init.sh
+++ b/tests/init.sh
@@ -317,6 +317,11 @@ path_prepend_ ()

 setup_ ()
 {
+  # If we're redirecting a file descriptor larger than 2, say via automake's
+  # TESTS_ENVIRONMENT, that redirected FD is closed-on-exec on some systems
+  # (at least Solaris 10 and HP-UX 11.x), so redirect it here again.
+  test $stderr_fileno_ = 2 || eval "exec $stderr_fileno_>&2"
+
   if test "$VERBOSE" = yes; then
     # Test whether set -x may cause the selected shell to corrupt an
     # application's stderr.  Many do, including zsh-4.3.10 and the /bin/sh
--
1.7.6.rc0.293.g40857