changeset 10684:d5d208d973af

Test against another AIX bug.
author Bruno Haible <bruno@clisp.org>
date Mon, 20 Oct 2008 13:10:37 +0200
parents b8ed97decfee
children 6473cab5bf8b
files ChangeLog m4/posix_spawn.m4
diffstat 2 files changed, 167 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2008-10-20  Bruno Haible  <bruno@clisp.org>
+
+	* m4/posix_spawn.m4 (gl_POSIX_SPAWN_WORKS): Test against another bug
+	of posix_spawn on AIX 5.3.
+
 2008-10-20  Bruno Haible  <bruno@clisp.org>
 
 	* m4/posix_spawn.m4 (gl_POSIX_SPAWN_WORKS): Make the check on MacOS X.
--- a/m4/posix_spawn.m4
+++ b/m4/posix_spawn.m4
@@ -48,10 +48,13 @@
 ])
 
 dnl Test whether posix_spawn actually works.
-dnl posix_spawn on AIX 5.3..6.1 has a bug: When it fails to execute the
-dnl program, the child process exits with exit() rather than _exit(),
-dnl which causes the stdio buffers to be flushed. Reported by Rainer Tammer.
-dnl posix_spawn on AIX 5.3..6.1 has also a second bug: It does not work
+dnl posix_spawn on AIX 5.3..6.1 has two bugs:
+dnl 1) When it fails to execute the program, the child process exits with
+dnl    exit() rather than _exit(), which causes the stdio buffers to be
+dnl    flushed. Reported by Rainer Tammer.
+dnl 2) The posix_spawn_file_actions_addopen function does not support file
+dnl    names that contain a '*'.
+dnl posix_spawn on AIX 5.3..6.1 has also a third bug: It does not work
 dnl when POSIX threads are used. But we don't test against this bug here.
 AC_DEFUN([gl_POSIX_SPAWN_WORKS],
 [
@@ -199,6 +202,161 @@
             gl_cv_func_posix_spawn_works=no
           fi],
          [gl_cv_func_posix_spawn_works=no])
+       if test $gl_cv_func_posix_spawn_works = yes; then
+         AC_RUN_IFELSE([AC_LANG_SOURCE([[
+/* Test whether posix_spawn_file_actions_addopen supports filename arguments
+   that contain special characters such as '*'.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+extern char **environ;
+
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+#ifndef WTERMSIG
+# define WTERMSIG(x) ((x) & 0x7f)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(x) (WTERMSIG (x) == 0)
+#endif
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(x) (((x) >> 8) & 0xff)
+#endif
+
+#define CHILD_PROGRAM_FILENAME "conftest"
+#define DATA_FILENAME "conftest%=*#?"
+
+static int
+parent_main (void)
+{
+  FILE *fp;
+  char *argv[3] = { CHILD_PROGRAM_FILENAME, "-child", NULL };
+  posix_spawn_file_actions_t actions;
+  bool actions_allocated;
+  int err;
+  pid_t child;
+  int status;
+  int exitstatus;
+
+  /* Create a data file with specific contents.  */
+  fp = fopen (DATA_FILENAME, "wb");
+  if (fp == NULL)
+    {
+      perror ("cannot create data file");
+      return 1;
+    }
+  fwrite ("Halle Potta", 1, 11, fp);
+  if (fflush (fp) || fclose (fp))
+    {
+      perror ("cannot prepare data file");
+      return 1;
+    }
+
+  /* Avoid reading from our stdin, as it could block.  */
+  freopen ("/dev/null", "rb", stdin);
+
+  /* Test whether posix_spawn_file_actions_addopen with this file name
+     actually works, but spawning a child that reads from this file.  */
+  actions_allocated = false;
+  if ((err = posix_spawn_file_actions_init (&actions)) != 0
+      || (actions_allocated = true,
+          (err = posix_spawn_file_actions_addopen (&actions, STDIN_FILENO, DATA_FILENAME, O_RDONLY, 0600)) != 0
+          || (err = posix_spawn (&child, CHILD_PROGRAM_FILENAME, &actions, NULL, argv, environ)) != 0))
+    {
+      if (actions_allocated)
+        posix_spawn_file_actions_destroy (&actions);
+      errno = err;
+      perror ("subprocess failed");
+      return 1;
+    }
+  posix_spawn_file_actions_destroy (&actions);
+  status = 0;
+  while (waitpid (child, &status, 0) != child)
+    ;
+  if (!WIFEXITED (status))
+    {
+      fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
+      return 1;
+    }
+  exitstatus = WEXITSTATUS (status);
+  if (exitstatus != 0)
+    {
+      fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
+      return 1;
+    }
+  return 0;
+}
+
+static int
+child_main (void)
+{
+  char buf[1024];
+
+  /* See if reading from STDIN_FILENO yields the expected contents.  */
+  if (fread (buf, 1, sizeof (buf), stdin) == 11
+      && memcmp (buf, "Halle Potta", 11) == 0)
+    return 0;
+  else
+    return 2;
+}
+
+static void
+cleanup_then_die (int sig)
+{
+  /* Clean up data file.  */
+  unlink (DATA_FILENAME);
+
+  /* Re-raise the signal and die from it.  */
+  signal (sig, SIG_DFL);
+  raise (sig);
+}
+
+int
+main (int argc, char *argv[])
+{
+  int exitstatus;
+
+  if (!(argc > 1 && strcmp (argv[1], "-child") == 0))
+    {
+      /* This is the parent process.  */
+      signal (SIGINT, cleanup_then_die);
+      signal (SIGTERM, cleanup_then_die);
+      #ifdef SIGHUP
+      signal (SIGHUP, cleanup_then_die);
+      #endif
+
+      exitstatus = parent_main ();
+    }
+  else
+    {
+      /* This is the child process.  */
+
+      exitstatus = child_main ();
+    }
+  unlink (DATA_FILENAME);
+  return exitstatus;
+}
+]])],
+           [],
+           [gl_cv_func_posix_spawn_works=no])
+       fi
      else
        case "$host_os" in
          aix*) gl_cv_func_posix_spawn_works="guessing no";;