1
# posix_spawn.m4 serial 11
2
dnl Copyright (C) 2008-2012 Free Software Foundation, Inc.
3
dnl This file is free software; the Free Software Foundation
4
dnl gives unlimited permission to copy and/or distribute it,
5
dnl with or without modifications, as long as this notice is preserved.
7
dnl Tests whether the entire posix_spawn facility is available.
8
AC_DEFUN([gl_POSIX_SPAWN],
10
AC_REQUIRE([gl_POSIX_SPAWN_BODY])
13
AC_DEFUN([gl_POSIX_SPAWN_BODY],
15
AC_REQUIRE([gl_SPAWN_H_DEFAULTS])
16
AC_REQUIRE([gl_HAVE_POSIX_SPAWN])
17
dnl Assume that when the main function exists, all the others,
18
dnl except posix_spawnattr_{get,set}sched*, are available as well.
19
dnl AC_CHECK_FUNCS_ONCE([posix_spawnp])
20
dnl AC_CHECK_FUNCS_ONCE([posix_spawn_file_actions_init])
21
dnl AC_CHECK_FUNCS_ONCE([posix_spawn_file_actions_addclose])
22
dnl AC_CHECK_FUNCS_ONCE([posix_spawn_file_actions_adddup2])
23
dnl AC_CHECK_FUNCS_ONCE([posix_spawn_file_actions_addopen])
24
dnl AC_CHECK_FUNCS_ONCE([posix_spawn_file_actions_destroy])
25
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_init])
26
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getflags])
27
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setflags])
28
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getpgroup])
29
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setpgroup])
30
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getsigdefault])
31
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setsigdefault])
32
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getsigmask])
33
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setsigmask])
34
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_destroy])
35
if test $ac_cv_func_posix_spawn = yes; then
37
case "$gl_cv_func_posix_spawn_works" in
39
AC_DEFINE([HAVE_WORKING_POSIX_SPAWN], [1],
40
[Define if you have the posix_spawn and posix_spawnp functions and
42
dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDULER
43
dnl evaluates to nonzero.
44
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedpolicy])
45
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedpolicy])
46
AC_CACHE_CHECK([whether posix_spawnattr_setschedpolicy is supported],
47
[gl_cv_func_spawnattr_setschedpolicy],
48
[AC_EGREP_CPP([POSIX scheduling supported], [
50
#if POSIX_SPAWN_SETSCHEDULER
51
POSIX scheduling supported
54
[gl_cv_func_spawnattr_setschedpolicy=yes],
55
[gl_cv_func_spawnattr_setschedpolicy=no])
57
dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDPARAM
58
dnl evaluates to nonzero.
59
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedparam])
60
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedparam])
61
AC_CACHE_CHECK([whether posix_spawnattr_setschedparam is supported],
62
[gl_cv_func_spawnattr_setschedparam],
63
[AC_EGREP_CPP([POSIX scheduling supported], [
65
#if POSIX_SPAWN_SETSCHEDPARAM
66
POSIX scheduling supported
69
[gl_cv_func_spawnattr_setschedparam=yes],
70
[gl_cv_func_spawnattr_setschedparam=no])
73
*) REPLACE_POSIX_SPAWN=1 ;;
78
dnl Test whether posix_spawn actually works.
79
dnl posix_spawn on AIX 5.3..6.1 has two bugs:
80
dnl 1) When it fails to execute the program, the child process exits with
81
dnl exit() rather than _exit(), which causes the stdio buffers to be
82
dnl flushed. Reported by Rainer Tammer.
83
dnl 2) The posix_spawn_file_actions_addopen function does not support file
84
dnl names that contain a '*'.
85
dnl posix_spawn on AIX 5.3..6.1 has also a third bug: It does not work
86
dnl when POSIX threads are used. But we don't test against this bug here.
87
AC_DEFUN([gl_POSIX_SPAWN_WORKS],
89
AC_REQUIRE([AC_PROG_CC])
90
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
91
AC_CACHE_CHECK([whether posix_spawn works], [gl_cv_func_posix_spawn_works],
92
[if test $cross_compiling = no; then
93
AC_LINK_IFELSE([AC_LANG_SOURCE([[
103
#include <sys/types.h>
104
#include <sys/wait.h>
106
extern char **environ;
109
# define STDIN_FILENO 0
111
#ifndef STDOUT_FILENO
112
# define STDOUT_FILENO 1
114
#ifndef STDERR_FILENO
115
# define STDERR_FILENO 2
119
# define WTERMSIG(x) ((x) & 0x7f)
122
# define WIFEXITED(x) (WTERMSIG (x) == 0)
125
# define WEXITSTATUS(x) (((x) >> 8) & 0xff)
128
#define CHILD_PROGRAM_FILENAME "/non/exist/ent"
133
if (0 <= fd && fd <= 2)
135
int f = fd_safer (dup (fd));
148
char *argv[2] = { CHILD_PROGRAM_FILENAME, NULL };
150
sigset_t blocked_signals;
151
sigset_t fatal_signal_set;
152
posix_spawn_file_actions_t actions;
153
bool actions_allocated;
154
posix_spawnattr_t attrs;
155
bool attrs_allocated;
161
setvbuf (stdout, NULL, _IOFBF, 0);
162
puts ("This should be seen only once.");
163
if (pipe (ofd) < 0 || (ofd[1] = fd_safer (ofd[1])) < 0)
165
perror ("cannot create pipe");
168
sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
169
sigemptyset (&fatal_signal_set);
170
sigaddset (&fatal_signal_set, SIGINT);
171
sigaddset (&fatal_signal_set, SIGTERM);
172
sigaddset (&fatal_signal_set, SIGHUP);
173
sigaddset (&fatal_signal_set, SIGPIPE);
174
sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
175
actions_allocated = false;
176
attrs_allocated = false;
177
if ((err = posix_spawn_file_actions_init (&actions)) != 0
178
|| (actions_allocated = true,
179
(err = posix_spawn_file_actions_adddup2 (&actions, ofd[0], STDIN_FILENO)) != 0
180
|| (err = posix_spawn_file_actions_addclose (&actions, ofd[0])) != 0
181
|| (err = posix_spawn_file_actions_addclose (&actions, ofd[1])) != 0
182
|| (err = posix_spawnattr_init (&attrs)) != 0
183
|| (attrs_allocated = true,
184
(err = posix_spawnattr_setsigmask (&attrs, &blocked_signals)) != 0
185
|| (err = posix_spawnattr_setflags (&attrs, POSIX_SPAWN_SETSIGMASK)) != 0)
186
|| (err = posix_spawnp (&child, CHILD_PROGRAM_FILENAME, &actions, &attrs, argv, environ)) != 0))
188
if (actions_allocated)
189
posix_spawn_file_actions_destroy (&actions);
191
posix_spawnattr_destroy (&attrs);
192
sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
198
perror ("subprocess failed");
202
posix_spawn_file_actions_destroy (&actions);
203
posix_spawnattr_destroy (&attrs);
204
sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
208
while (waitpid (child, &status, 0) != child)
210
if (!WIFEXITED (status))
212
fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
215
exitstatus = WEXITSTATUS (status);
216
if (exitstatus != 127)
218
fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
224
[if test -s conftest$ac_exeext \
225
&& ./conftest$ac_exeext > conftest.out \
226
&& echo 'This should be seen only once.' > conftest.ok \
227
&& cmp conftest.out conftest.ok > /dev/null; then
228
gl_cv_func_posix_spawn_works=yes
230
gl_cv_func_posix_spawn_works=no
232
[gl_cv_func_posix_spawn_works=no])
233
if test $gl_cv_func_posix_spawn_works = yes; then
234
AC_RUN_IFELSE([AC_LANG_SOURCE([[
235
/* Test whether posix_spawn_file_actions_addopen supports filename arguments
236
that contain special characters such as '*'. */
246
#include <sys/types.h>
247
#include <sys/wait.h>
249
extern char **environ;
252
# define STDIN_FILENO 0
254
#ifndef STDOUT_FILENO
255
# define STDOUT_FILENO 1
257
#ifndef STDERR_FILENO
258
# define STDERR_FILENO 2
262
# define WTERMSIG(x) ((x) & 0x7f)
265
# define WIFEXITED(x) (WTERMSIG (x) == 0)
268
# define WEXITSTATUS(x) (((x) >> 8) & 0xff)
271
#define CHILD_PROGRAM_FILENAME "conftest"
272
#define DATA_FILENAME "conftest%=*#?"
278
char *argv[3] = { CHILD_PROGRAM_FILENAME, "-child", NULL };
279
posix_spawn_file_actions_t actions;
280
bool actions_allocated;
286
/* Create a data file with specific contents. */
287
fp = fopen (DATA_FILENAME, "wb");
290
perror ("cannot create data file");
293
fwrite ("Halle Potta", 1, 11, fp);
294
if (fflush (fp) || fclose (fp))
296
perror ("cannot prepare data file");
300
/* Avoid reading from our stdin, as it could block. */
301
freopen ("/dev/null", "rb", stdin);
303
/* Test whether posix_spawn_file_actions_addopen with this file name
304
actually works, but spawning a child that reads from this file. */
305
actions_allocated = false;
306
if ((err = posix_spawn_file_actions_init (&actions)) != 0
307
|| (actions_allocated = true,
308
(err = posix_spawn_file_actions_addopen (&actions, STDIN_FILENO, DATA_FILENAME, O_RDONLY, 0600)) != 0
309
|| (err = posix_spawn (&child, CHILD_PROGRAM_FILENAME, &actions, NULL, argv, environ)) != 0))
311
if (actions_allocated)
312
posix_spawn_file_actions_destroy (&actions);
314
perror ("subprocess failed");
317
posix_spawn_file_actions_destroy (&actions);
319
while (waitpid (child, &status, 0) != child)
321
if (!WIFEXITED (status))
323
fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
326
exitstatus = WEXITSTATUS (status);
329
fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
340
/* See if reading from STDIN_FILENO yields the expected contents. */
341
if (fread (buf, 1, sizeof (buf), stdin) == 11
342
&& memcmp (buf, "Halle Potta", 11) == 0)
349
cleanup_then_die (int sig)
351
/* Clean up data file. */
352
unlink (DATA_FILENAME);
354
/* Re-raise the signal and die from it. */
355
signal (sig, SIG_DFL);
360
main (int argc, char *argv[])
364
if (!(argc > 1 && strcmp (argv[1], "-child") == 0))
366
/* This is the parent process. */
367
signal (SIGINT, cleanup_then_die);
368
signal (SIGTERM, cleanup_then_die);
370
signal (SIGHUP, cleanup_then_die);
373
exitstatus = parent_main ();
377
/* This is the child process. */
379
exitstatus = child_main ();
381
unlink (DATA_FILENAME);
386
[gl_cv_func_posix_spawn_works=no])
390
aix*) gl_cv_func_posix_spawn_works="guessing no";;
391
*) gl_cv_func_posix_spawn_works="guessing yes";;
397
# Prerequisites of lib/spawni.c.
398
AC_DEFUN([gl_PREREQ_POSIX_SPAWN_INTERNAL],
400
AC_CHECK_HEADERS([paths.h])
401
AC_CHECK_FUNCS([confstr sched_setparam sched_setscheduler setegid seteuid vfork])
404
AC_DEFUN([gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE],
406
AC_REQUIRE([gl_SPAWN_H_DEFAULTS])
407
AC_REQUIRE([AC_PROG_CC])
408
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
410
if test $REPLACE_POSIX_SPAWN = 1; then
411
REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE=1
413
dnl On Solaris 11 2011-11, posix_spawn_file_actions_addclose succeeds even
414
dnl if the fd argument is out of range.
415
AC_CACHE_CHECK([whether posix_spawn_file_actions_addclose works],
416
[gl_cv_func_posix_spawn_file_actions_addclose_works],
422
posix_spawn_file_actions_t actions;
423
if (posix_spawn_file_actions_init (&actions) != 0)
425
if (posix_spawn_file_actions_addclose (&actions, 10000000) == 0)
429
[gl_cv_func_posix_spawn_file_actions_addclose_works=yes],
430
[gl_cv_func_posix_spawn_file_actions_addclose_works=no],
431
[# Guess no on Solaris, yes otherwise.
433
solaris*) gl_cv_func_posix_spawn_file_actions_addclose_works="guessing no";;
434
*) gl_cv_func_posix_spawn_file_actions_addclose_works="guessing yes";;
438
case "$gl_cv_func_posix_spawn_file_actions_addclose_works" in
440
*) REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE=1 ;;
445
AC_DEFUN([gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2],
447
AC_REQUIRE([gl_SPAWN_H_DEFAULTS])
448
AC_REQUIRE([AC_PROG_CC])
449
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
451
if test $REPLACE_POSIX_SPAWN = 1; then
452
REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2=1
454
dnl On Solaris 11 2011-11, posix_spawn_file_actions_adddup2 succeeds even
455
dnl if the fd argument is out of range.
456
AC_CACHE_CHECK([whether posix_spawn_file_actions_adddup2 works],
457
[gl_cv_func_posix_spawn_file_actions_adddup2_works],
463
posix_spawn_file_actions_t actions;
464
if (posix_spawn_file_actions_init (&actions) != 0)
466
if (posix_spawn_file_actions_adddup2 (&actions, 10000000, 2) == 0)
470
[gl_cv_func_posix_spawn_file_actions_adddup2_works=yes],
471
[gl_cv_func_posix_spawn_file_actions_adddup2_works=no],
472
[# Guess no on Solaris, yes otherwise.
474
solaris*) gl_cv_func_posix_spawn_file_actions_adddup2_works="guessing no";;
475
*) gl_cv_func_posix_spawn_file_actions_adddup2_works="guessing yes";;
479
case "$gl_cv_func_posix_spawn_file_actions_adddup2_works" in
481
*) REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2=1 ;;
486
AC_DEFUN([gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN],
488
AC_REQUIRE([gl_SPAWN_H_DEFAULTS])
489
AC_REQUIRE([AC_PROG_CC])
490
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
492
if test $REPLACE_POSIX_SPAWN = 1; then
493
REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN=1
495
dnl On Solaris 11 2011-11, posix_spawn_file_actions_addopen succeeds even
496
dnl if the fd argument is out of range.
497
AC_CACHE_CHECK([whether posix_spawn_file_actions_addopen works],
498
[gl_cv_func_posix_spawn_file_actions_addopen_works],
505
posix_spawn_file_actions_t actions;
506
if (posix_spawn_file_actions_init (&actions) != 0)
508
if (posix_spawn_file_actions_addopen (&actions, 10000000, "foo", 0, O_RDONLY)
513
[gl_cv_func_posix_spawn_file_actions_addopen_works=yes],
514
[gl_cv_func_posix_spawn_file_actions_addopen_works=no],
515
[# Guess no on Solaris, yes otherwise.
517
solaris*) gl_cv_func_posix_spawn_file_actions_addopen_works="guessing no";;
518
*) gl_cv_func_posix_spawn_file_actions_addopen_works="guessing yes";;
522
case "$gl_cv_func_posix_spawn_file_actions_addopen_works" in
524
*) REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN=1 ;;