comparison libgfortran/intrinsics/execute_command_line.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
1 /* Implementation of the EXECUTE_COMMAND_LINE intrinsic. 1 /* Implementation of the EXECUTE_COMMAND_LINE intrinsic.
2 Copyright (C) 2009-2018 Free Software Foundation, Inc. 2 Copyright (C) 2009-2020 Free Software Foundation, Inc.
3 Contributed by François-Xavier Coudert. 3 Contributed by François-Xavier Coudert.
4 4
5 This file is part of the GNU Fortran runtime library (libgfortran). 5 This file is part of the GNU Fortran runtime library (libgfortran).
6 6
7 Libgfortran is free software; you can redistribute it and/or modify it under 7 Libgfortran is free software; you can redistribute it and/or modify it under
30 #include <unistd.h> 30 #include <unistd.h>
31 #endif 31 #endif
32 #ifdef HAVE_SYS_WAIT_H 32 #ifdef HAVE_SYS_WAIT_H
33 #include <sys/wait.h> 33 #include <sys/wait.h>
34 #endif 34 #endif
35 35 #ifdef HAVE_POSIX_SPAWN
36 #include <spawn.h>
37 extern char **environ;
38 #endif
39 #if defined(HAVE_POSIX_SPAWN) || defined(HAVE_FORK)
40 #include <signal.h>
41 #endif
36 42
37 enum { EXEC_SYNCHRONOUS = -2, EXEC_NOERROR = 0, EXEC_SYSTEMFAILED, 43 enum { EXEC_SYNCHRONOUS = -2, EXEC_NOERROR = 0, EXEC_SYSTEMFAILED,
38 EXEC_CHILDFAILED, EXEC_INVALIDCOMMAND }; 44 EXEC_CHILDFAILED, EXEC_INVALIDCOMMAND };
39 static const char *cmdmsg_values[] = 45 static const char *cmdmsg_values[] =
40 { "", 46 { "",
57 runtime_error ("%s", msg); 63 runtime_error ("%s", msg);
58 } 64 }
59 } 65 }
60 66
61 67
68 #if defined(HAVE_WAITPID) && defined(HAVE_SIGACTION)
69 static void
70 sigchld_handler (int signum __attribute__((unused)))
71 {
72 while (waitpid ((pid_t)(-1), NULL, WNOHANG) > 0) {}
73 }
74 #endif
75
62 static void 76 static void
63 execute_command_line (const char *command, bool wait, int *exitstat, 77 execute_command_line (const char *command, bool wait, int *exitstat,
64 int *cmdstat, char *cmdmsg, 78 int *cmdstat, char *cmdmsg,
65 gfc_charlen_type command_len, 79 gfc_charlen_type command_len,
66 gfc_charlen_type cmdmsg_len) 80 gfc_charlen_type cmdmsg_len)
69 char *cmd = fc_strdup (command, command_len); 83 char *cmd = fc_strdup (command, command_len);
70 84
71 /* Flush all I/O units before executing the command. */ 85 /* Flush all I/O units before executing the command. */
72 flush_all_units(); 86 flush_all_units();
73 87
74 #if defined(HAVE_FORK) 88 #if defined(HAVE_POSIX_SPAWN) || defined(HAVE_FORK)
75 if (!wait) 89 if (!wait)
76 { 90 {
77 /* Asynchronous execution. */ 91 /* Asynchronous execution. */
78 pid_t pid; 92 pid_t pid;
79 93
80 set_cmdstat (cmdstat, EXEC_NOERROR); 94 set_cmdstat (cmdstat, EXEC_NOERROR);
81 95
96 #if defined(HAVE_SIGACTION) && defined(HAVE_WAITPID)
97 static bool sig_init_saved;
98 bool sig_init = __atomic_load_n (&sig_init_saved, __ATOMIC_RELAXED);
99 if (!sig_init)
100 {
101 struct sigaction sa;
102 sa.sa_handler = &sigchld_handler;
103 sigemptyset(&sa.sa_mask);
104 sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
105 sigaction(SIGCHLD, &sa, 0);
106 __atomic_store_n (&sig_init_saved, true, __ATOMIC_RELAXED);
107 }
108 #endif
109
110 #ifdef HAVE_POSIX_SPAWN
111 const char * const argv[] = {"sh", "-c", cmd, NULL};
112 if (posix_spawn (&pid, "/bin/sh", NULL, NULL,
113 (char * const* restrict) argv, environ))
114 set_cmdstat (cmdstat, EXEC_CHILDFAILED);
115 #elif defined(HAVE_FORK)
82 if ((pid = fork()) < 0) 116 if ((pid = fork()) < 0)
83 set_cmdstat (cmdstat, EXEC_CHILDFAILED); 117 set_cmdstat (cmdstat, EXEC_CHILDFAILED);
84 else if (pid == 0) 118 else if (pid == 0)
85 { 119 {
86 /* Child process. */ 120 /* Child process. */
87 int res = system (cmd); 121 int res = system (cmd);
88 _exit (WIFEXITED(res) ? WEXITSTATUS(res) : res); 122 _exit (WIFEXITED(res) ? WEXITSTATUS(res) : res);
89 } 123 }
124 #endif
90 } 125 }
91 else 126 else
92 #endif 127 #endif
93 { 128 {
94 /* Synchronous execution. */ 129 /* Synchronous execution. */
95 int res = system (cmd); 130 int res = system (cmd);
96 131
97 if (res == -1) 132 if (res == -1)
98 set_cmdstat (cmdstat, EXEC_SYSTEMFAILED); 133 set_cmdstat (cmdstat, EXEC_SYSTEMFAILED);
99 #ifndef HAVE_FORK 134 #if !defined(HAVE_POSIX_SPAWN) && !defined(HAVE_FORK)
100 else if (!wait) 135 else if (!wait)
101 set_cmdstat (cmdstat, EXEC_SYNCHRONOUS); 136 set_cmdstat (cmdstat, EXEC_SYNCHRONOUS);
102 #endif 137 #endif
103 else if (res == 127 || res == 126 138 else if (res == 127 || res == 126
104 #if defined(WEXITSTATUS) && defined(WIFEXITED) 139 #if defined(WEXITSTATUS) && defined(WIFEXITED)