diff options
Diffstat (limited to 'coreutils/timeout.c')
-rw-r--r-- | coreutils/timeout.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/coreutils/timeout.c b/coreutils/timeout.c index 84299a0a5..58f96192b 100644 --- a/coreutils/timeout.c +++ b/coreutils/timeout.c | |||
@@ -43,10 +43,35 @@ | |||
43 | //usage:#define timeout_full_usage "\n\n" | 43 | //usage:#define timeout_full_usage "\n\n" |
44 | //usage: "Run PROG. Send SIG to it if it is not gone in SECS seconds.\n" | 44 | //usage: "Run PROG. Send SIG to it if it is not gone in SECS seconds.\n" |
45 | //usage: "Default SIG: TERM." | 45 | //usage: "Default SIG: TERM." |
46 | //usage: IF_PLATFORM_MINGW32("\n") | ||
46 | //usage: "If it still exists in KILL_SECS seconds, send KILL.\n" | 47 | //usage: "If it still exists in KILL_SECS seconds, send KILL.\n" |
47 | 48 | ||
48 | #include "libbb.h" | 49 | #include "libbb.h" |
49 | 50 | ||
51 | #if ENABLE_PLATFORM_MINGW32 | ||
52 | static HANDLE child = INVALID_HANDLE_VALUE; | ||
53 | |||
54 | static void kill_child(void) | ||
55 | { | ||
56 | if (child != INVALID_HANDLE_VALUE) { | ||
57 | pid_t pid = (pid_t)GetProcessId(child); | ||
58 | if (pid) | ||
59 | kill(pid, SIGTERM); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | /* Return TRUE if child exits before timeout expires */ | ||
64 | static NOINLINE int timeout_wait(duration_t timeout, HANDLE proc, DWORD *status) | ||
65 | { | ||
66 | DWORD t = (DWORD)(timeout * 1000); | ||
67 | if (WaitForSingleObject(proc, t) == WAIT_OBJECT_0) { | ||
68 | /* process is gone */ | ||
69 | GetExitCodeProcess(proc, status); | ||
70 | return TRUE; | ||
71 | } | ||
72 | return FALSE; | ||
73 | } | ||
74 | #else | ||
50 | static NOINLINE int timeout_wait(duration_t timeout, pid_t pid) | 75 | static NOINLINE int timeout_wait(duration_t timeout, pid_t pid) |
51 | { | 76 | { |
52 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ | 77 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ |
@@ -66,13 +91,19 @@ static NOINLINE int timeout_wait(duration_t timeout, pid_t pid) | |||
66 | } | 91 | } |
67 | return EXIT_FAILURE; | 92 | return EXIT_FAILURE; |
68 | } | 93 | } |
94 | #endif | ||
69 | 95 | ||
70 | int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 96 | int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
71 | int timeout_main(int argc UNUSED_PARAM, char **argv) | 97 | int timeout_main(int argc UNUSED_PARAM, char **argv) |
72 | { | 98 | { |
73 | int signo; | 99 | int signo; |
100 | #if !ENABLE_PLATFORM_MINGW32 | ||
74 | int status; | 101 | int status; |
75 | int parent = 0; | 102 | int parent = 0; |
103 | #else | ||
104 | intptr_t ret; | ||
105 | DWORD status = EXIT_SUCCESS; | ||
106 | #endif | ||
76 | duration_t timeout; | 107 | duration_t timeout; |
77 | duration_t kill_timeout; | 108 | duration_t kill_timeout; |
78 | pid_t pid; | 109 | pid_t pid; |
@@ -82,15 +113,27 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
82 | const char *opt_s = "TERM"; | 113 | const char *opt_s = "TERM"; |
83 | char *opt_k = NULL; | 114 | char *opt_k = NULL; |
84 | 115 | ||
116 | #if ENABLE_PLATFORM_MINGW32 | ||
117 | xfunc_error_retval = 125; | ||
118 | #endif | ||
119 | |||
85 | /* -p option is not documented, it is needed to support NOMMU. */ | 120 | /* -p option is not documented, it is needed to support NOMMU. */ |
86 | 121 | ||
87 | /* -t SECONDS; -p PARENT_PID */ | 122 | /* -t SECONDS; -p PARENT_PID */ |
88 | /* '+': stop at first non-option */ | 123 | /* '+': stop at first non-option */ |
124 | #if !ENABLE_PLATFORM_MINGW32 | ||
89 | getopt32(argv, "+s:k:" USE_FOR_NOMMU("p:+"), &opt_s, &opt_k, &parent); | 125 | getopt32(argv, "+s:k:" USE_FOR_NOMMU("p:+"), &opt_s, &opt_k, &parent); |
126 | #else | ||
127 | getopt32(argv, "+s:k:", &opt_s, &opt_k); | ||
128 | #endif | ||
90 | /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ | 129 | /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ |
91 | 130 | ||
92 | signo = get_signum(opt_s); | 131 | signo = get_signum(opt_s); |
132 | #if !ENABLE_PLATFORM_MINGW32 | ||
93 | if (signo < 0) | 133 | if (signo < 0) |
134 | #else | ||
135 | if (!is_valid_signal(signo)) | ||
136 | #endif | ||
94 | bb_error_msg_and_die("unknown signal '%s'", opt_s); | 137 | bb_error_msg_and_die("unknown signal '%s'", opt_s); |
95 | 138 | ||
96 | kill_timeout = 0; | 139 | kill_timeout = 0; |
@@ -103,6 +146,7 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
103 | if (!argv[optind]) /* no PROG? */ | 146 | if (!argv[optind]) /* no PROG? */ |
104 | bb_show_usage(); | 147 | bb_show_usage(); |
105 | 148 | ||
149 | #if !ENABLE_PLATFORM_MINGW32 | ||
106 | /* We want to create a grandchild which will watch | 150 | /* We want to create a grandchild which will watch |
107 | * and kill the grandparent. Other methods: | 151 | * and kill the grandparent. Other methods: |
108 | * making parent watch child disrupts parent<->child link | 152 | * making parent watch child disrupts parent<->child link |
@@ -155,4 +199,33 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
155 | argv[1] = sv2; | 199 | argv[1] = sv2; |
156 | #endif | 200 | #endif |
157 | BB_EXECVP_or_die(argv); | 201 | BB_EXECVP_or_die(argv); |
202 | #else /* ENABLE_PLATFORM_MINGW32 */ | ||
203 | argv += optind; | ||
204 | if ((ret=mingw_spawn_proc((const char **)argv)) == -1) { | ||
205 | xfunc_error_retval = errno == EACCES ? 126 : 127; | ||
206 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | ||
207 | } | ||
208 | |||
209 | child = (HANDLE)ret; | ||
210 | atexit(kill_child); | ||
211 | if (timeout_wait(timeout, child, &status)) | ||
212 | goto finish; | ||
213 | status = signo == SIGKILL ? 137 : 124; | ||
214 | |||
215 | pid = (pid_t)GetProcessId(child); | ||
216 | if (pid) { | ||
217 | kill(pid, signo); | ||
218 | |||
219 | if (kill_timeout > 0) { | ||
220 | if (timeout_wait(kill_timeout, child, &status)) | ||
221 | goto finish; | ||
222 | kill(pid, SIGKILL); | ||
223 | status = 137; | ||
224 | } | ||
225 | } | ||
226 | finish: | ||
227 | CloseHandle(child); | ||
228 | child = INVALID_HANDLE_VALUE; | ||
229 | return status; | ||
230 | #endif | ||
158 | } | 231 | } |