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-16 Janne Blomqvist <j...@gcc.gnu.org> PR libfortran/90038 * configure.ac (AC_CHECK_FUNCS_ONCE): Check for posix_spawn instead of fork. * intrinsics/execute_command_line (execute_command_line): Use posix_spawn instead of fork. * Makefile.in: Regenerated. * config.h.in: Regenerated. * configure: Regenerated. Regtested on x86_64-pc-linux-gnu, Ok for trunk? --- libgfortran/configure.ac | 2 +- libgfortran/intrinsics/execute_command_line.c | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac index c06db7b1a78..66af512a292 100644 --- a/libgfortran/configure.ac +++ b/libgfortran/configure.ac @@ -315,7 +315,7 @@ else AC_CHECK_FUNCS_ONCE(getrusage times mkstemp strtof strtold snprintf \ ftruncate chsize chdir getentropy getlogin gethostname kill link symlink \ sleep ttyname \ - alarm access fork setmode fcntl writev \ + alarm access posix_spawn setmode fcntl writev \ gettimeofday stat fstat lstat getpwuid vsnprintf dup \ getcwd localtime_r gmtime_r getpwuid_r ttyname_r clock_gettime \ getgid getpid getuid geteuid umask getegid \ diff --git a/libgfortran/intrinsics/execute_command_line.c b/libgfortran/intrinsics/execute_command_line.c index a234bc328b5..3df99c10678 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) if (!wait) { /* Asynchronous execution. */ @@ -79,14 +82,10 @@ execute_command_line (const char *command, bool wait, int *exitstat, set_cmdstat (cmdstat, EXEC_NOERROR); - if ((pid = fork()) < 0) + 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); - else if (pid == 0) - { - /* Child process. */ - int res = system (cmd); - _exit (WIFEXITED(res) ? WEXITSTATUS(res) : res); - } } else #endif @@ -96,7 +95,7 @@ execute_command_line (const char *command, bool wait, int *exitstat, if (res == -1) set_cmdstat (cmdstat, EXEC_SYSTEMFAILED); -#ifndef HAVE_FORK +#ifndef HAVE_POSIX_SPAWN else if (!wait) set_cmdstat (cmdstat, EXEC_SYNCHRONOUS); #endif -- 2.17.1