diff options
author | Janne Blomqvist <jb@gcc.gnu.org> | 2019-05-19 22:38:11 +0300 |
---|---|---|
committer | Janne Blomqvist <jb@gcc.gnu.org> | 2019-05-19 22:38:11 +0300 |
commit | ef536b413e077a87b15a11e60ca4c2675d11dccb (patch) | |
tree | a13eae10848d4fb1f477e179eefb5f27f860344a | |
parent | dbd5df2eb893bf5370fa3fdde6e09f21d4b26b79 (diff) | |
download | gcc-ef536b413e077a87b15a11e60ca4c2675d11dccb.tar.gz |
libfortran/90038 Reap dead children when wait=.false.
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-19 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.
Regtested on x86_64-pc-linux-gnu.
From-SVN: r271384
-rw-r--r-- | libgfortran/ChangeLog | 9 | ||||
-rw-r--r-- | libgfortran/config.h.in | 6 | ||||
-rwxr-xr-x | libgfortran/configure | 10 | ||||
-rw-r--r-- | libgfortran/configure.ac | 2 | ||||
-rw-r--r-- | libgfortran/intrinsics/execute_command_line.c | 25 |
5 files changed, 49 insertions, 3 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index e0bf369561b..37e87fbe4bd 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,12 @@ +2019-05-19 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. + 2019-05-17 Janne Blomqvist <jb@gcc.gnu.org> PR libfortran/90038 diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in index da3968cb94f..44786399987 100644 --- a/libgfortran/config.h.in +++ b/libgfortran/config.h.in @@ -666,6 +666,9 @@ /* 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 @@ -831,6 +834,9 @@ /* 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 diff --git a/libgfortran/configure b/libgfortran/configure index 094c7325189..60867b93d0e 100755 --- a/libgfortran/configure +++ b/libgfortran/configure @@ -2638,6 +2638,8 @@ 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" @@ -12698,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 12701 "configure" +#line 12703 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12804,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 12807 "configure" +#line 12809 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -16976,6 +16978,10 @@ done + + + + fi # Check strerror_r, cannot be above as versions with two and three arguments exist diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac index 8fd5a1a30a9..7cfce28ab69 100644 --- a/libgfortran/configure.ac +++ b/libgfortran/configure.ac @@ -314,7 +314,7 @@ 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 \ + 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 \ diff --git a/libgfortran/intrinsics/execute_command_line.c b/libgfortran/intrinsics/execute_command_line.c index 2ef2324b243..1a471632172 100644 --- a/libgfortran/intrinsics/execute_command_line.c +++ b/libgfortran/intrinsics/execute_command_line.c @@ -36,6 +36,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #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 }; @@ -62,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, @@ -82,6 +93,20 @@ execute_command_line (const char *command, bool wait, int *exitstat, set_cmdstat (cmdstat, EXEC_NOERROR); +#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, |