diff options
author | Janne Blomqvist <jb@gcc.gnu.org> | 2019-05-17 21:18:04 +0300 |
---|---|---|
committer | Janne Blomqvist <jb@gcc.gnu.org> | 2019-05-17 21:18:04 +0300 |
commit | f888603842067252f8a9d14eaa9d070ae7b00662 (patch) | |
tree | c99a2f356406142291186a4b7102a86f67f29579 /libgfortran/intrinsics/execute_command_line.c | |
parent | 8ee47828d226e2041ac0f3b5b8c1aed43cec24a4 (diff) | |
download | gcc-f888603842067252f8a9d14eaa9d070ae7b00662.zip gcc-f888603842067252f8a9d14eaa9d070ae7b00662.tar.gz gcc-f888603842067252f8a9d14eaa9d070ae7b00662.tar.bz2 |
libfortran/90038: Use posix_spawn instead of fork
fork() semantics can be problematic. Most unix style OS'es have
posix_spawn which can be used to replace fork + exec in many cases.
For more information see
e.g. https://www.microsoft.com/en-us/research/uploads/prod/2019/04/fork-hotos19.pdf
This replaces the one use of fork in libgfortran with posix_spawn.
2019-05-17 Janne Blomqvist <jb@gcc.gnu.org>
PR libfortran/90038
* configure.ac (AC_CHECK_FUNCS_ONCE): Check for posix_spawn.
* intrinsics/execute_command_line (execute_command_line): Use
posix_spawn.
* Makefile.in: Regenerated.
* config.h.in: Regenerated.
* configure: Regenerated.
Regtested on x86_64-pc-linux-gnu.
From-SVN: r271340
Diffstat (limited to 'libgfortran/intrinsics/execute_command_line.c')
-rw-r--r-- | libgfortran/intrinsics/execute_command_line.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/libgfortran/intrinsics/execute_command_line.c b/libgfortran/intrinsics/execute_command_line.c index a234bc3..2ef2324 100644 --- a/libgfortran/intrinsics/execute_command_line.c +++ b/libgfortran/intrinsics/execute_command_line.c @@ -32,7 +32,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> #endif - +#ifdef HAVE_POSIX_SPAWN +#include <spawn.h> +extern char **environ; +#endif enum { EXEC_SYNCHRONOUS = -2, EXEC_NOERROR = 0, EXEC_SYSTEMFAILED, EXEC_CHILDFAILED, EXEC_INVALIDCOMMAND }; @@ -71,7 +74,7 @@ execute_command_line (const char *command, bool wait, int *exitstat, /* Flush all I/O units before executing the command. */ flush_all_units(); -#if defined(HAVE_FORK) +#if defined(HAVE_POSIX_SPAWN) || defined(HAVE_FORK) if (!wait) { /* Asynchronous execution. */ @@ -79,14 +82,21 @@ execute_command_line (const char *command, bool wait, int *exitstat, set_cmdstat (cmdstat, EXEC_NOERROR); - if ((pid = fork()) < 0) +#ifdef HAVE_POSIX_SPAWN + const char * const argv[] = {"sh", "-c", cmd, NULL}; + if (posix_spawn (&pid, "/bin/sh", NULL, NULL, + (char * const* restrict) argv, environ)) set_cmdstat (cmdstat, EXEC_CHILDFAILED); +#elif defined(HAVE_FORK) + if ((pid = fork()) < 0) + set_cmdstat (cmdstat, EXEC_CHILDFAILED); else if (pid == 0) { /* Child process. */ int res = system (cmd); _exit (WIFEXITED(res) ? WEXITSTATUS(res) : res); } +#endif } else #endif @@ -96,7 +106,7 @@ execute_command_line (const char *command, bool wait, int *exitstat, if (res == -1) set_cmdstat (cmdstat, EXEC_SYSTEMFAILED); -#ifndef HAVE_FORK +#if !defined(HAVE_POSIX_SPAWN) && !defined(HAVE_FORK) else if (!wait) set_cmdstat (cmdstat, EXEC_SYNCHRONOUS); #endif |