diff --git a/libiberty/aclocal.m4 b/libiberty/aclocal.m4 index 0757688d52a..f327865aaf9 100644 --- a/libiberty/aclocal.m4 +++ b/libiberty/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15.1 -*- Autoconf -*- +# generated automatically by aclocal 1.16.5 -*- Autoconf -*- -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2021 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff --git a/libiberty/config.in b/libiberty/config.in index f7052b5d958..050f6cd1961 100644 --- a/libiberty/config.in +++ b/libiberty/config.in @@ -198,6 +198,12 @@ /* Define to 1 if you have the `pipe2' function. */ #undef HAVE_PIPE2 +/* Define to 1 if you have the `posix_spawn' function. */ +#undef HAVE_POSIX_SPAWN + +/* Define to 1 if you have the `posix_spawnp' function. */ +#undef HAVE_POSIX_SPAWNP + /* Define to 1 if you have the header file. */ #undef HAVE_PROCESS_H @@ -249,6 +255,9 @@ /* Define to 1 if you have the `spawnvpe' function. */ #undef HAVE_SPAWNVPE +/* Define to 1 if you have the header file. */ +#undef HAVE_SPAWN_H + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H diff --git a/libiberty/configure b/libiberty/configure index dd896270dc6..dba458f6bc1 100755 --- a/libiberty/configure +++ b/libiberty/configure @@ -5655,7 +5655,7 @@ host_makefile_frag=${frag} # It's OK to check for header files. Although the compiler may not be # able to link anything, it had better be able to at least compile # something. -for ac_header in sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h +for ac_header in sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h spawn.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header" @@ -6164,7 +6164,8 @@ funcs="$funcs setproctitle" vars="sys_errlist sys_nerr sys_siglist" checkfuncs="__fsetlocking canonicalize_file_name dup3 getrlimit getrusage \ - getsysinfo gettimeofday on_exit pipe2 psignal pstat_getdynamic pstat_getstatic \ + getsysinfo gettimeofday on_exit pipe2 posix_spawn posix_spawnp psignal \ + pstat_getdynamic pstat_getstatic \ realpath setrlimit spawnve spawnvpe strerror strsignal sysconf sysctl \ sysmp table times wait3 wait4" @@ -6187,7 +6188,8 @@ if test "x" = "y"; then index insque \ memchr memcmp memcpy memmem memmove memset mkstemps \ on_exit \ - pipe2 psignal pstat_getdynamic pstat_getstatic putenv \ + pipe2 posix_spawn posix_spawnp psignal \ + pstat_getdynamic pstat_getstatic putenv \ random realpath rename rindex \ sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \ stpcpy stpncpy strcasecmp strchr strdup \ diff --git a/libiberty/configure.ac b/libiberty/configure.ac index 0748c592704..2488b031bc8 100644 --- a/libiberty/configure.ac +++ b/libiberty/configure.ac @@ -289,7 +289,7 @@ AC_SUBST_FILE(host_makefile_frag) # It's OK to check for header files. Although the compiler may not be # able to link anything, it had better be able to at least compile # something. -AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h) +AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h spawn.h) AC_HEADER_SYS_WAIT AC_HEADER_TIME @@ -412,7 +412,8 @@ funcs="$funcs setproctitle" vars="sys_errlist sys_nerr sys_siglist" checkfuncs="__fsetlocking canonicalize_file_name dup3 getrlimit getrusage \ - getsysinfo gettimeofday on_exit pipe2 psignal pstat_getdynamic pstat_getstatic \ + getsysinfo gettimeofday on_exit pipe2 posix_spawn posix_spawnp psignal \ + pstat_getdynamic pstat_getstatic \ realpath setrlimit spawnve spawnvpe strerror strsignal sysconf sysctl \ sysmp table times wait3 wait4" @@ -435,7 +436,8 @@ if test "x" = "y"; then index insque \ memchr memcmp memcpy memmem memmove memset mkstemps \ on_exit \ - pipe2 psignal pstat_getdynamic pstat_getstatic putenv \ + pipe2 posix_spawn posix_spawnp psignal \ + pstat_getdynamic pstat_getstatic putenv \ random realpath rename rindex \ sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \ stpcpy stpncpy strcasecmp strchr strdup \ diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c index 33b5bce31c2..ee52789d264 100644 --- a/libiberty/pex-unix.c +++ b/libiberty/pex-unix.c @@ -58,6 +58,9 @@ extern int errno; #ifdef HAVE_PROCESS_H #include #endif +#ifdef HAVE_SPAWN_H +#include +#endif #ifdef vfork /* Autoconf may define this to fork for us. */ # define VFORK_STRING "fork" @@ -559,6 +562,171 @@ pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, return (pid_t) -1; } +#elif defined(HAVE_POSIX_SPAWN) && defined(HAVE_POSIX_SPAWNP) +/* Implementation of pex->exec_child using posix_spawn. */ + +static pid_t +pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, + int flags, const char *executable, + char * const * argv, char * const * env, + int in, int out, int errdes, + int toclose, const char **errmsg, int *err) +{ + int ret; + pid_t pid = -1; + posix_spawnattr_t attr; + posix_spawn_file_actions_t actions; + int attr_initialized = 0, actions_initialized = 0; + + *err = 0; + + ret = posix_spawnattr_init (&attr); + if (ret) + { + *err = ret; + *errmsg = "posix_spawnattr_init"; + goto exit; + } + attr_initialized = 1; + + /* Use vfork() on glibc <=2.24. */ +#ifdef POSIX_SPAWN_USEVFORK + ret = posix_spawnattr_setflags (&attr, POSIX_SPAWN_USEVFORK); + if (ret) + { + *err = ret; + *errmsg = "posix_spawnattr_setflags"; + goto exit; + } +#endif + + ret = posix_spawn_file_actions_init (&actions); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_init"; + goto exit; + } + actions_initialized = 1; + + if (in != STDIN_FILE_NO) + { + ret = posix_spawn_file_actions_adddup2 (&actions, in, STDIN_FILE_NO); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_adddup2"; + goto exit; + } + + ret = posix_spawn_file_actions_addclose (&actions, in); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_addclose"; + goto exit; + } + } + + if (out != STDOUT_FILE_NO) + { + ret = posix_spawn_file_actions_adddup2 (&actions, out, STDOUT_FILE_NO); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_adddup2"; + goto exit; + } + + ret = posix_spawn_file_actions_addclose (&actions, out); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_addclose"; + goto exit; + } + } + + if (errdes != STDERR_FILE_NO) + { + ret = posix_spawn_file_actions_adddup2 (&actions, errdes, STDERR_FILE_NO); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_adddup2"; + goto exit; + } + + ret = posix_spawn_file_actions_addclose (&actions, errdes); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_addclose"; + goto exit; + } + } + + if (toclose >= 0) + { + ret = posix_spawn_file_actions_addclose (&actions, toclose); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_addclose"; + goto exit; + } + } + + if ((flags & PEX_STDERR_TO_STDOUT) != 0) + { + ret = posix_spawn_file_actions_adddup2 (&actions, STDOUT_FILE_NO, STDERR_FILE_NO); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn_file_actions_adddup2"; + goto exit; + } + } + + if ((flags & PEX_SEARCH) != 0) + { + ret = posix_spawnp (&pid, executable, &actions, &attr, argv, env ? env : environ); + if (ret) + { + *err = ret; + *errmsg = "posix_spawnp"; + goto exit; + } + } + else + { + ret = posix_spawn (&pid, executable, &actions, &attr, argv, env ? env : environ); + if (ret) + { + *err = ret; + *errmsg = "posix_spawn"; + goto exit; + } + } + +exit: + if (actions_initialized) + posix_spawn_file_actions_destroy (&actions); + if (attr_initialized) + posix_spawnattr_destroy (&attr); + + if (!*err && in != STDIN_FILE_NO) + if (close (in)) + *errmsg = "close", *err = errno, pid = -1; + if (!*err && out != STDOUT_FILE_NO) + if (close (out)) + *errmsg = "close", *err = errno, pid = -1; + if (!*err && errdes != STDERR_FILE_NO) + if (close (errdes)) + *errmsg = "close", *err = errno, pid = -1; + + return pid; +} #else /* Implementation of pex->exec_child using standard vfork + exec. */