X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=m4%2Fposix_spawn.m4;h=40df135ae9048aa29a63430f222c99136cd18843;hb=df8bc51660941d7464dcd31170690519cb95c0c2;hp=f0e84c911230305d49908d58168bf0253dd17f33;hpb=60c92ef259a263829a026c7017faa729150c4551;p=gnulib.git diff --git a/m4/posix_spawn.m4 b/m4/posix_spawn.m4 index f0e84c911..40df135ae 100644 --- a/m4/posix_spawn.m4 +++ b/m4/posix_spawn.m4 @@ -1,5 +1,5 @@ -# posix_spawn.m4 serial 2 -dnl Copyright (C) 2008 Free Software Foundation, Inc. +# posix_spawn.m4 serial 7 +dnl Copyright (C) 2008-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -13,9 +13,9 @@ AC_DEFUN([gl_POSIX_SPAWN], AC_DEFUN([gl_POSIX_SPAWN_BODY], [ AC_REQUIRE([gl_SPAWN_H_DEFAULTS]) - AC_CHECK_FUNCS_ONCE([posix_spawn]) - dnl Assume that when the main function exists, all the others are - dnl available as well. + AC_REQUIRE([gl_HAVE_POSIX_SPAWN]) + dnl Assume that when the main function exists, all the others, + dnl except posix_spawnattr_{get,set}sched*, are available as well. dnl AC_CHECK_FUNCS_ONCE([posix_spawnp]) dnl AC_CHECK_FUNCS_ONCE([posix_spawn_file_actions_init]) dnl AC_CHECK_FUNCS_ONCE([posix_spawn_file_actions_addclose]) @@ -27,10 +27,6 @@ AC_DEFUN([gl_POSIX_SPAWN_BODY], dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setflags]) dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getpgroup]) dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setpgroup]) - dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedparam]) - dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedparam]) - dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedpolicy]) - dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedpolicy]) dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getsigdefault]) dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setsigdefault]) dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getsigmask]) @@ -39,19 +35,51 @@ AC_DEFUN([gl_POSIX_SPAWN_BODY], if test $ac_cv_func_posix_spawn = yes; then gl_POSIX_SPAWN_WORKS case "$gl_cv_func_posix_spawn_works" in - *yes) ;; + *yes) + dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDULER + dnl evaluates to nonzero. + dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedpolicy]) + dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedpolicy]) + AC_CACHE_CHECK([whether posix_spawnattr_setschedpolicy is supported], + [gl_cv_func_spawnattr_setschedpolicy], + [AC_EGREP_CPP([POSIX scheduling supported], [ +#include +#if POSIX_SPAWN_SETSCHEDULER + POSIX scheduling supported +#endif +], + [gl_cv_func_spawnattr_setschedpolicy=yes], + [gl_cv_func_spawnattr_setschedpolicy=no]) + ]) + dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDPARAM + dnl evaluates to nonzero. + dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedparam]) + dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedparam]) + AC_CACHE_CHECK([whether posix_spawnattr_setschedparam is supported], + [gl_cv_func_spawnattr_setschedparam], + [AC_EGREP_CPP([POSIX scheduling supported], [ +#include +#if POSIX_SPAWN_SETSCHEDPARAM + POSIX scheduling supported +#endif +], + [gl_cv_func_spawnattr_setschedparam=yes], + [gl_cv_func_spawnattr_setschedparam=no]) + ]) + ;; *) REPLACE_POSIX_SPAWN=1 ;; esac - else - HAVE_POSIX_SPAWN=0 fi ]) 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], [ @@ -59,7 +87,7 @@ AC_DEFUN([gl_POSIX_SPAWN_WORKS], AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles AC_CACHE_CHECK([whether posix_spawn works], [gl_cv_func_posix_spawn_works], [if test $cross_compiling = no; then - AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + AC_LINK_IFELSE([AC_LANG_SOURCE([[ #include #include #include @@ -87,20 +115,11 @@ extern char **environ; #ifndef WTERMSIG # define WTERMSIG(x) ((x) & 0x7f) #endif -#ifndef WCOREDUMP -# define WCOREDUMP(x) ((x) & 0x80) -#endif -#ifndef WEXITSTATUS -# define WEXITSTATUS(x) (((x) >> 8) & 0xff) -#endif -#ifndef WIFSIGNALED -# define WIFSIGNALED(x) (WTERMSIG (x) != 0 && WTERMSIG(x) != 0x7f) -#endif #ifndef WIFEXITED # define WIFEXITED(x) (WTERMSIG (x) == 0) #endif -#ifndef WIFSTOPPED -# define WIFSTOPPED(x) (WTERMSIG (x) == 0x7f) +#ifndef WEXITSTATUS +# define WEXITSTATUS(x) (((x) >> 8) & 0xff) #endif #define CHILD_PROGRAM_FILENAME "/non/exist/ent" @@ -118,10 +137,11 @@ fd_safer (int fd) } return fd; -} -]], -dnl Now comes the main() function. -[[ +} + +int +main () +{ char *argv[2] = { CHILD_PROGRAM_FILENAME, NULL }; int ofd[2]; sigset_t blocked_signals; @@ -163,13 +183,18 @@ dnl Now comes the main() function. || (err = posix_spawnp (&child, CHILD_PROGRAM_FILENAME, &actions, &attrs, argv, environ)) != 0)) { if (actions_allocated) - posix_spawn_file_actions_destroy (&actions); + posix_spawn_file_actions_destroy (&actions); if (attrs_allocated) - posix_spawnattr_destroy (&attrs); + posix_spawnattr_destroy (&attrs); sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL); - errno = err; - perror ("subprocess failed"); - exit (1); + if (err == ENOENT) + return 0; + else + { + errno = err; + perror ("subprocess failed"); + exit (1); + } } posix_spawn_file_actions_destroy (&actions); posix_spawnattr_destroy (&attrs); @@ -190,6 +215,8 @@ dnl Now comes the main() function. fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus); exit (1); } + return 0; +} ]])], [if test -s conftest$ac_exeext \ && ./conftest$ac_exeext > conftest.out \ @@ -200,6 +227,161 @@ dnl Now comes the main() function. 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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";;