bug-gnulib
[Top][All Lists]
Advanced

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

another posix_spawn bug on AIX


From: Bruno Haible
Subject: another posix_spawn bug on AIX
Date: Mon, 20 Oct 2008 13:19:41 +0200
User-agent: KMail/1.5.4

The implementation of posix_spawn on AIX 5.3..6.1 has yet another bug: it fails
when asked to open a file whose name contains a '*'. Apparently the implementors
(from a subcontractor of IBM, not IBM itself, I am being told) just took the
primitive sample implementation from
  <http://www.opengroup.org/onlinepubs/000095399/xrat/xsh_chap03.html>

This patch adds a test against this bug.


2008-10-20  Bruno Haible  <address@hidden>

        * m4/posix_spawn.m4 (gl_POSIX_SPAWN_WORKS): Test against another bug
        of posix_spawn on AIX 5.3.

*** m4/posix_spawn.m4.orig      2008-10-20 13:09:09.000000000 +0200
--- m4/posix_spawn.m4   2008-10-20 13:09:03.000000000 +0200
***************
*** 48,57 ****
  ])
  
  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 when POSIX threads are used. But we don't test against this bug here.
  AC_DEFUN([gl_POSIX_SPAWN_WORKS],
  [
--- 48,60 ----
  ])
  
  dnl Test whether posix_spawn actually works.
! 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,204 ****
--- 202,362 ----
              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";;





reply via email to

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