summaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2019-05-19 22:38:11 +0300
committerJanne Blomqvist <jb@gcc.gnu.org>2019-05-19 22:38:11 +0300
commitef536b413e077a87b15a11e60ca4c2675d11dccb (patch)
treea13eae10848d4fb1f477e179eefb5f27f860344a /libgfortran
parentdbd5df2eb893bf5370fa3fdde6e09f21d4b26b79 (diff)
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
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog9
-rw-r--r--libgfortran/config.h.in6
-rwxr-xr-xlibgfortran/configure10
-rw-r--r--libgfortran/configure.ac2
-rw-r--r--libgfortran/intrinsics/execute_command_line.c25
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,