[git commit] timeout: add support for "timeout -k KILL_SECS"

Denys Vlasenko vda.linux at googlemail.com
Fri Dec 17 22:11:17 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=7d49fedc86bec300d22f44f93ec95825320dd1c1
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at mafoo.org.uk>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 coreutils/timeout.c | 43 ++++++++++++++++++++++++++++++++-----------
 1 file 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;
 	}
 


More information about the busybox-cvs mailing list