Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.busybox.net/busybox.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Slowe <foo@mafoo.org.uk>2021-10-09 14:26:40 +0300
committerDenys Vlasenko <vda.linux@googlemail.com>2021-12-18 01:11:17 +0300
commit7d49fedc86bec300d22f44f93ec95825320dd1c1 (patch)
tree0bb535177a75500ebc5ecef1a2d07b7c023d838f
parentc1eac153e8b89cfc9d550991735c09bad1579201 (diff)
timeout: add support for "timeout -k KILL_SECS"
function old new delta timeout_main 307 373 +66 timeout_wait - 42 +42 .rodata 104201 104203 +2 packed_usage 34097 34096 -1 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/1 up/down: 110/-1) Total: 109 bytes Signed-off-by: Matthew Slowe <foo@mafoo.org.uk> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--coreutils/timeout.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/coreutils/timeout.c b/coreutils/timeout.c
index 8485e1e7d..06108f315 100644
--- a/coreutils/timeout.c
+++ b/coreutils/timeout.c
@@ -39,13 +39,29 @@
//kbuild:lib-$(CONFIG_TIMEOUT) += timeout.o
//usage:#define timeout_trivial_usage
-//usage: "[-s SIG] SECS PROG ARGS"
+//usage: "[-s SIG] [-k KILL_SECS] SECS PROG ARGS"
//usage:#define timeout_full_usage "\n\n"
//usage: "Run PROG. Send SIG to it if it is not gone in SECS seconds.\n"
//usage: "Default SIG: TERM."
+//usage: "If it still exists in KILL_SECS seconds, send KILL.\n"
#include "libbb.h"
+static NOINLINE int timeout_wait(int timeout, pid_t pid)
+{
+ /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */
+ while (1) {
+ sleep1();
+ if (--timeout <= 0)
+ break;
+ if (kill(pid, 0)) {
+ /* process is gone */
+ return EXIT_SUCCESS;
+ }
+ }
+ return EXIT_FAILURE;
+}
+
int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int timeout_main(int argc UNUSED_PARAM, char **argv)
{
@@ -53,23 +69,29 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
int status;
int parent = 0;
int timeout;
+ int kill_timeout;
pid_t pid;
#if !BB_MMU
char *sv1, *sv2;
#endif
const char *opt_s = "TERM";
+ char *opt_k = NULL;
/* -p option is not documented, it is needed to support NOMMU. */
/* -t SECONDS; -p PARENT_PID */
/* '+': stop at first non-option */
- getopt32(argv, "+s:" USE_FOR_NOMMU("p:+"), &opt_s, &parent);
+ getopt32(argv, "+s:k:" USE_FOR_NOMMU("p:+"), &opt_s, &opt_k, &parent);
/*argv += optind; - no, wait for bb_daemonize_or_rexec! */
signo = get_signum(opt_s);
if (signo < 0)
bb_error_msg_and_die("unknown signal '%s'", opt_s);
+ kill_timeout = 0;
+ if (opt_k)
+ kill_timeout = parse_duration_str(opt_k);
+
if (!argv[optind])
bb_show_usage();
timeout = parse_duration_str(argv[optind++]);
@@ -103,17 +125,16 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
bb_daemonize_or_rexec(0, argv);
/* Here we are grandchild. Sleep, then kill grandparent */
grandchild:
- /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */
- while (1) {
- sleep1();
- if (--timeout <= 0)
- break;
- if (kill(parent, 0)) {
- /* process is gone */
+ if (timeout_wait(timeout, parent) == EXIT_SUCCESS)
+ return EXIT_SUCCESS;
+ kill(parent, signo);
+
+ if (kill_timeout > 0) {
+ if (timeout_wait(kill_timeout, parent) == EXIT_SUCCESS)
return EXIT_SUCCESS;
- }
+ kill(parent, SIGKILL);
}
- kill(parent, signo);
+
return EXIT_SUCCESS;
}