bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

spawn-pipe tests on OSF/1


From: Bruno Haible
Subject: spawn-pipe tests on OSF/1
Date: Mon, 6 Jun 2011 11:39:08 +0200
User-agent: KMail/1.9.9

On OSF/1 5.1 with cc (but not with gcc), and only in the gettext build, not in
testdirs, I see a test failure like this:

test-spawn-pipe.c:80: assertion failed
(null): 
/home/haible/gettext-0.18.2/gettext-tools/gnulib-tests/.libs/lt-test-spawn-pipe 
subprocess got fatal signal 6
test-spawn-pipe.sh: iteration 0 failed
test-spawn-pipe.c:80: assertion failed
(null): 
/home/haible/gettext-0.18.2/gettext-tools/gnulib-tests/.libs/lt-test-spawn-pipe 
subprocess got fatal signal 6
test-spawn-pipe.sh: iteration 1 failed
test-spawn-pipe.c:80: assertion failed
(null): 
/home/haible/gettext-0.18.2/gettext-tools/gnulib-tests/.libs/lt-test-spawn-pipe 
subprocess got fatal signal 6
test-spawn-pipe.sh: iteration 2 failed
test-spawn-pipe.c:80: assertion failed
(null): 
/home/haible/gettext-0.18.2/gettext-tools/gnulib-tests/.libs/lt-test-spawn-pipe 
subprocess got fatal signal 6
test-spawn-pipe.sh: iteration 3 failed
test-spawn-pipe.c:70: assertion failed
test-spawn-pipe.sh: iteration 4 failed
test-spawn-pipe.c:70: assertion failed
test-spawn-pipe.sh: iteration 5 failed
test-spawn-pipe.c:70: assertion failed
test-spawn-pipe.sh: iteration 6 failed
test-spawn-pipe.c:70: assertion failed
test-spawn-pipe.sh: iteration 7 failed
FAIL: test-spawn-pipe.sh

That is, when we expect the file descriptors 3..7 to be closed, fd 3 is
actually open.

This failure is probably due to the many libraries against which the child
program is linked:

$ ldd gettext-0.18.2/gettext-tools/gnulib-tests/.libs/*test-spawn-pipe*

        Main  =>   
gettext-0.18.2/gettext-tools/gnulib-tests/.libs/lt-test-spawn-pipe
        libiconv.so.2  =>   /home/haible/prefix-osf51-cc/lib/libiconv.so.2
        libgettextlib-0.18.2.so  =>   
/home/haible/gettext-0.18.2/gettext-tools/gnulib-lib/.libs/libgettextlib-0.18.2.so
        libpacl.so  =>   /usr/shlib/libpacl.so
        libintl.so.8  =>   
/home/haible/gettext-0.18.2/gettext-tools/intl/.libs/libintl.so.8
        libcurses.so  =>   /usr/shlib/libcurses.so
        libc.so  =>   /usr/shlib/libc.so
        libots3.so  =>   /usr/shlib/libots3.so
        libpset.so  =>   /usr/shlib/libpset.so
        libpthread.so  =>   /usr/shlib/libpthread.so
        libexc.so  =>   /usr/shlib/libexc.so
        libproplist.so  =>   /usr/shlib/libproplist.so
        libmach.so  =>   /usr/shlib/libmach.so
        libnuma.so  =>   /usr/shlib/libnuma.so

Another (less likely) hypothesis is that the wrapper script from libtool is
interfering during the exec call.

In either case, the workaround is to ensure that the child program is not
linked against $(LDADD) and also does not use libtool. This patch fixes it.


2011-06-06  Bruno Haible  <address@hidden>

        spawn-pipe tests: Like the child program only against libc.
        * tests/test-spawn-pipe-child.c: New file, extracted from
        tests/test-spawn-pipe.c.
        (main): Expect only one argument.
        (is_open): New function, copied from tests/test-pipe.c.
        * tests/test-spawn-pipe.c: Don't include <errno.h>.
        (child_main): Remove function.
        (test_pipe): Pass only one argument to the child program.
        (main): Remove child process code. Expect the child program's name as
        first argument.
        * tests/test-spawn-pipe.sh: Pass the child program's name as first
        argument.
        * modules/spawn-pipe-tests (Files): Add tests/test-spawn-pipe-child.c.
        (Makefile.am): Add test-spawn-pipe-child to check_PROGRAMS. Link
        test-spawn-pipe-child against no libraries.

======================== tests/test-spawn-pipe-child.c ========================
/* Child program invoked by test-spawn-pipe..
   Copyright (C) 2009-2011 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include <config.h>

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* Get declarations of the Win32 API functions.  */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif

/* Depending on arguments, this test intentionally closes stderr or
   starts life with stderr closed.  So, we arrange to have fd 10
   (outside the range of interesting fd's during the test) set up to
   duplicate the original stderr.  */

#define BACKUP_STDERR_FILENO 10
#define ASSERT_STREAM myerr
#include "macros.h"

static FILE *myerr;

/* In this file, we use only system functions, no overrides from gnulib.  */
#undef atoi
#undef close
#undef fcntl
#undef fdopen
#undef read
#undef write

/* Return non-zero if FD is open.  */
static int
is_open (int fd)
{
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  /* On Win32, the initial state of unassigned standard file
     descriptors is that they are open but point to an
     INVALID_HANDLE_VALUE, and there is no fcntl.  */
  return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
#else
# ifndef F_GETFL
#  error Please port fcntl to your platform
# endif
  return 0 <= fcntl (fd, F_GETFL);
#endif
}

int
main (int argc, char *argv[])
{
  char buffer[2] = { 's', 't' };
  int fd;

  /* fd 2 might be closed, but fd BACKUP_STDERR_FILENO is the original
     stderr.  */
  myerr = fdopen (BACKUP_STDERR_FILENO, "w");
  if (!myerr)
    return 2;

  ASSERT (argc == 2);

  /* Read one byte from fd 0, and write its value plus one to fd 1.
     fd 2 should be closed iff the argument is 1.  Check that no other file
     descriptors leaked.  */

  ASSERT (read (STDIN_FILENO, buffer, 2) == 1);

  buffer[0]++;
  ASSERT (write (STDOUT_FILENO, buffer, 1) == 1);

  switch (atoi (argv[1]))
    {
    case 0:
      /* Expect fd 2 is open.  */
      ASSERT (is_open (STDERR_FILENO));
      break;
    case 1:
      /* Expect fd 2 is closed.  */
      ASSERT (! is_open (STDERR_FILENO));
      break;
    default:
      ASSERT (0);
    }

  for (fd = 3; fd < 7; fd++)
    {
      errno = 0;
      ASSERT (close (fd) == -1);
      ASSERT (errno == EBADF);
    }

  return 0;
}
===============================================================================
--- tests/test-spawn-pipe.c.orig        Mon Jun  6 11:19:19 2011
+++ tests/test-spawn-pipe.c     Mon Jun  6 02:40:54 2011
@@ -20,7 +20,6 @@
 #include "spawn-pipe.h"
 #include "wait-process.h"
 
-#include <errno.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -38,70 +37,23 @@
 
 static FILE *myerr;
 
-/* Code executed by the child process.  argv[1] = "child".  */
-static int
-child_main (int argc, char *argv[])
-{
-  char buffer[2] = { 's', 't' };
-  int fd;
-  int ret;
-
-  ASSERT (argc == 3);
-
-  /* Read one byte from fd 0, and write its value plus one to fd 1.
-     fd 2 should be closed iff the argument is 1.  Check that no other file
-     descriptors leaked.  */
-
-  ASSERT (read (STDIN_FILENO, buffer, 2) == 1);
-
-  buffer[0]++;
-  ASSERT (write (STDOUT_FILENO, buffer, 1) == 1);
-
-  errno = 0;
-  ret = dup2 (STDERR_FILENO, STDERR_FILENO);
-  switch (atoi (argv[2]))
-    {
-    case 0:
-      /* Expect fd 2 is open.  */
-      ASSERT (ret == STDERR_FILENO);
-      break;
-    case 1:
-      /* Expect fd 2 is closed.  */
-      ASSERT (ret == -1);
-      ASSERT (errno == EBADF);
-      break;
-    default:
-      ASSERT (false);
-    }
-
-  for (fd = 3; fd < 7; fd++)
-    {
-      errno = 0;
-      ASSERT (close (fd) == -1);
-      ASSERT (errno == EBADF);
-    }
-
-  return 0;
-}
-
 /* Create a bi-directional pipe to a test child, and validate that the
-   child program returns the expected output.  The child is the same
-   program as the parent ARGV0, but with different arguments.
+   child program returns the expected output.
+   PROG is the program to run in the child process.
    STDERR_CLOSED is true if we have already closed fd 2.  */
 static void
-test_pipe (const char *argv0, bool stderr_closed)
+test_pipe (const char *prog, bool stderr_closed)
 {
   int fd[2];
-  char *argv[4];
+  char *argv[3];
   pid_t pid;
   char buffer[2] = { 'a', 't' };
 
   /* Set up child.  */
-  argv[0] = (char *) argv0;
-  argv[1] = (char *) "child";
-  argv[2] = (char *) (stderr_closed ? "1" : "0");
-  argv[3] = NULL;
-  pid = create_pipe_bidi (argv0, argv0, argv, false, true, true, fd);
+  argv[0] = (char *) prog;
+  argv[1] = (char *) (stderr_closed ? "1" : "0");
+  argv[2] = NULL;
+  pid = create_pipe_bidi (prog, prog, argv, false, true, true, fd);
   ASSERT (0 <= pid);
   ASSERT (STDERR_FILENO < fd[0]);
   ASSERT (STDERR_FILENO < fd[1]);
@@ -114,7 +66,7 @@
   ASSERT (read (fd[0], buffer, 2) == 1);
 
   /* Wait for child.  */
-  ASSERT (wait_subprocess (pid, argv0, true, false, true, true, NULL) == 0);
+  ASSERT (wait_subprocess (pid, prog, true, false, true, true, NULL) == 0);
   ASSERT (close (fd[0]) == 0);
 
   /* Check the result.  */
@@ -122,18 +74,25 @@
   ASSERT (buffer[1] == 't');
 }
 
-/* Code executed by the parent process.  */
-static int
-parent_main (int argc, char *argv[])
+int
+main (int argc, char *argv[])
 {
   int test;
   int fd;
 
-  ASSERT (argc == 2);
+  if (argc != 3)
+    {
+      fprintf (stderr, "%s: need 2 arguments\n", argv[0]);
+      return 2;
+    }
+  /* We might close fd 2 later, so save it in fd 10.  */
+  if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
+      || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
+    return 2;
 
   /* Selectively close various standard fds, to verify the child process is
      not impacted by this.  */
-  test = atoi (argv[1]);
+  test = atoi (argv[2]);
   switch (test)
     {
     case 0:
@@ -174,31 +133,7 @@
   for (fd = 3; fd < 7; fd++)
     close (fd);
 
-  test_pipe (argv[0], test >= 4);
+  test_pipe (argv[1], test >= 4);
 
   return 0;
 }
-
-int
-main (int argc, char *argv[])
-{
-  if (argc < 2)
-    {
-      fprintf (stderr, "%s: need arguments\n", argv[0]);
-      return 2;
-    }
-  if (strcmp (argv[1], "child") == 0)
-    {
-      /* fd 2 might be closed, but fd BACKUP_STDERR_FILENO is the original
-         stderr.  */
-      myerr = fdopen (BACKUP_STDERR_FILENO, "w");
-      if (!myerr)
-        return 2;
-      return child_main (argc, argv);
-    }
-  /* We might close fd 2 later, so save it in fd 10.  */
-  if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
-      || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
-    return 2;
-  return parent_main (argc, argv);
-}
--- tests/test-spawn-pipe.sh.orig       Mon Jun  6 11:19:19 2011
+++ tests/test-spawn-pipe.sh    Mon Jun  6 02:35:33 2011
@@ -2,7 +2,7 @@
 
 st=0
 for i in 0 1 2 3 4 5 6 7 ; do
-  ./test-spawn-pipe${EXEEXT} $i \
+  ./test-spawn-pipe${EXEEXT} ./test-spawn-pipe-child${EXEEXT} $i \
     || { echo test-spawn-pipe.sh: iteration $i failed >&2; st=1; }
 done
 exit $st
--- modules/spawn-pipe-tests.orig       Mon Jun  6 11:19:19 2011
+++ modules/spawn-pipe-tests    Mon Jun  6 02:34:47 2011
@@ -1,6 +1,7 @@
 Files:
 tests/test-spawn-pipe.sh
 tests/test-spawn-pipe.c
+tests/test-spawn-pipe-child.c
 tests/macros.h
 
 Depends-on:
@@ -10,5 +11,9 @@
 
 Makefile.am:
 TESTS += test-spawn-pipe.sh
-check_PROGRAMS += test-spawn-pipe
+check_PROGRAMS += test-spawn-pipe test-spawn-pipe-child
 test_spawn_pipe_LDADD = $(LDADD) @LIBINTL@
+# The test-spawn-pipe-child program must be a real executable, not a libtool
+# wrapper script, and should link against as few libraries as possible.
+# Therefore don't link it against any libraries other than -lc.
+test_spawn_pipe_child_LDADD =

-- 
In memoriam Robert F. Kennedy <http://en.wikipedia.org/wiki/Robert_F._Kennedy>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]