]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libfortran/90038 Use posix_spawn, reap dead children when wait=.false.
authorJanne Blomqvist <jb@gcc.gnu.org>
Mon, 20 May 2019 17:43:05 +0000 (20:43 +0300)
committerJanne Blomqvist <jb@gcc.gnu.org>
Mon, 20 May 2019 17:43:05 +0000 (20:43 +0300)
Backport from trunk.

When using posix_spawn or fork to launch a child process, the parent
needs to wait for the child, otherwise the dead child is left as a
zombie process. For this purpose one can install a signal handler for
SIGCHLD.

2019-05-20  Janne Blomqvist  <jb@gcc.gnu.org>

PR libfortran/90038
* intrinsics/execute_command_line (sigchld_handler): New function.
        (execute_command_line): Install handler for SIGCHLD.
        * configure.ac: Check for presence of sigaction and waitpid.
        * config.h.in: Regenerated.
        * configure: Regenerated.

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-20  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: r271427

libgfortran/ChangeLog
libgfortran/Makefile.in
libgfortran/config.h.in
libgfortran/configure
libgfortran/configure.ac
libgfortran/intrinsics/execute_command_line.c

index ef74ebc779b205e63b044aea04cdb22b1a197737..fc354f9045eaa5b39cee0be9ca9458ef996f4328 100644 (file)
@@ -1,3 +1,24 @@
+2019-05-20  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       Backport from trunk
+        PR libfortran/90038
+        * intrinsics/execute_command_line (sigchld_handler): New function.
+        (execute_command_line): Install handler for SIGCHLD.
+        * configure.ac: Check for presence of sigaction and waitpid.
+        * config.h.in: Regenerated.
+        * configure: Regenerated.
+
+2019-05-20  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       Backport from trunk
+       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.
+
 2019-05-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR fortran/54613
index 954f9feb1eac668d5738097c7f135f89de21736e..6e9612df8ba55eb064eb72d75df722ed51ddf15c 100644 (file)
@@ -694,6 +694,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
index cbd720a26702e9471bc843045f5c3bdf1f2ce0ef..4478639998771b3d19756e5d185c136b320ede19 100644 (file)
 /* Define to 1 if we have POSIX getpwuid_r which takes 5 arguments. */
 #undef HAVE_POSIX_GETPWUID_R
 
+/* Define to 1 if you have the `posix_spawn' function. */
+#undef HAVE_POSIX_SPAWN
+
 /* Define to 1 if you have the `pow' function. */
 #undef HAVE_POW
 
 /* Define to 1 if you have the `setmode' function. */
 #undef HAVE_SETMODE
 
+/* Define to 1 if you have the `sigaction' function. */
+#undef HAVE_SIGACTION
+
 /* Define to 1 if you have the `sin' function. */
 #undef HAVE_SIN
 
 /* Define to 1 if you have the `vsnprintf' function. */
 #undef HAVE_VSNPRINTF
 
+/* Define to 1 if you have the `waitpid' function. */
+#undef HAVE_WAITPID
+
 /* Define if target has a reliable stat. */
 #undef HAVE_WORKING_STAT
 
index 487d8c090e2720c4638e5cbc6f77b1c3b9b755f6..60867b93d0e8d5fd2cb1744f1d340b99970d7db3 100755 (executable)
@@ -780,6 +780,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -870,6 +871,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1122,6 +1124,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1259,7 +1270,7 @@ fi
 for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
                datadir sysconfdir sharedstatedir localstatedir includedir \
                oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-               libdir localedir mandir
+               libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1412,6 +1423,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -2626,9 +2638,12 @@ as_fn_append ac_func_list " link"
 as_fn_append ac_func_list " symlink"
 as_fn_append ac_func_list " sleep"
 as_fn_append ac_func_list " ttyname"
+as_fn_append ac_func_list " sigaction"
+as_fn_append ac_func_list " waitpid"
 as_fn_append ac_func_list " alarm"
 as_fn_append ac_func_list " access"
 as_fn_append ac_func_list " fork"
+as_fn_append ac_func_list " posix_spawn"
 as_fn_append ac_func_list " setmode"
 as_fn_append ac_func_list " fcntl"
 as_fn_append ac_func_list " writev"
@@ -12685,7 +12700,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12688 "configure"
+#line 12703 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12791,7 +12806,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12794 "configure"
+#line 12809 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -16040,7 +16055,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -16086,7 +16101,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -16110,7 +16125,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -16155,7 +16170,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -16179,7 +16194,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -16954,6 +16969,12 @@ done
 
 
 
+
+
+
+
+
+
 
 
 
index c06db7b1a78967976765a11893435b7496809bb2..7cfce28ab697ee2c0353ce6a208e31b0d918c6f4 100644 (file)
@@ -314,8 +314,8 @@ if test "${hardwire_newlib:-0}" -eq 1; then
 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 \
+   sleep ttyname sigaction waitpid \
+   alarm access fork 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 \
index a234bc328b5def09b19bcf789071cb0ee1d6b2c8..1a47163217265ed19ef81d75b7a3b8e9cdd970ef 100644 (file)
@@ -32,7 +32,13 @@ 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
+#if defined(HAVE_POSIX_SPAWN) || defined(HAVE_FORK)
+#include <signal.h>
+#endif
 
 enum { EXEC_SYNCHRONOUS = -2, EXEC_NOERROR = 0, EXEC_SYSTEMFAILED,
        EXEC_CHILDFAILED, EXEC_INVALIDCOMMAND };
@@ -59,6 +65,14 @@ set_cmdstat (int *cmdstat, int value)
 }
 
 
+#if defined(HAVE_WAITPID) && defined(HAVE_SIGACTION)
+static void
+sigchld_handler (int signum __attribute__((unused)))
+{
+  while (waitpid ((pid_t)(-1), NULL, WNOHANG) > 0) {}
+}
+#endif
+
 static void
 execute_command_line (const char *command, bool wait, int *exitstat,
                      int *cmdstat, char *cmdmsg,
@@ -71,7 +85,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 +93,35 @@ execute_command_line (const char *command, bool wait, int *exitstat,
 
       set_cmdstat (cmdstat, EXEC_NOERROR);
 
-      if ((pid = fork()) < 0)
+#if defined(HAVE_SIGACTION) && defined(HAVE_WAITPID)
+      static bool sig_init_saved;
+      bool sig_init = __atomic_load_n (&sig_init_saved, __ATOMIC_RELAXED);
+      if (!sig_init)
+       {
+         struct sigaction sa;
+         sa.sa_handler = &sigchld_handler;
+         sigemptyset(&sa.sa_mask);
+         sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
+         sigaction(SIGCHLD, &sa, 0);
+         __atomic_store_n (&sig_init_saved, true, __ATOMIC_RELAXED);
+       }
+#endif
+
+#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 +131,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