[PATCH] timeout: Add support for "-k" parameter.

Matthew Slowe foo at mafoo.org.uk
Sat Oct 9 11:27:57 UTC 2021


Add support for GNU coreutils "-k" parameter to timeout applet.

This patch moves the timing and process checking code into a separate 
reusable function and adds a optional second timeout which will send a 
SIGKILL to the process if it's still alive.

The patch introduces a compiler warning about mismatched "const char *" 
and "char *". I've left a FIXME.

-- 
Matthew Slowe
-------------- next part --------------
From 8f508628564604a8f0d3fad27bac8981f8798f34 Mon Sep 17 00:00:00 2001
From: Matthew Slowe <foo at mafoo.org.uk>
Date: Sat, 9 Oct 2021 12:26:40 +0100
Subject: [PATCH] timeout: add support for "timeout -k KILL_SECS"

---
 coreutils/timeout.c | 47 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/coreutils/timeout.c b/coreutils/timeout.c
index 8485e1e7d..9ca699aeb 100644
--- a/coreutils/timeout.c
+++ b/coreutils/timeout.c
@@ -39,13 +39,27 @@
 //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:       "Run PROG. Send SIG to it if it is not gone in SECS seconds. If it is still not going in KILL_SECS seconds then send KILL to it.\n"
 //usage:       "Default SIG: TERM."
 
 #include "libbb.h"
 
+int timeout_wait(int timeout, pid_t pid);
+int timeout_wait(int timeout, pid_t pid) {
+	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 +67,34 @@ 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";
+	const char *opt_k = "0";
 
 	/* -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;
+	{
+		int opt_k_i;
+		/* FIXME: opt_k Declared const char* but discarded here */
+		opt_k_i = parse_duration_str(opt_k);
+		if(opt_k_i > 0)
+			kill_timeout = opt_k_i;
+	}
+
 	if (!argv[optind])
 		bb_show_usage();
 	timeout = parse_duration_str(argv[optind++]);
@@ -104,16 +129,16 @@ int timeout_main(int argc UNUSED_PARAM, char **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, pid) == EXIT_SUCCESS)
+			return EXIT_SUCCESS;
+		kill(parent, signo);
+
+		if(kill_timeout > 0) {
+			if(timeout_wait(kill_timeout, pid) == EXIT_SUCCESS)
 				return EXIT_SUCCESS;
-			}
+			kill(parent, SIGKILL);
 		}
-		kill(parent, signo);
+
 		return EXIT_SUCCESS;
 	}
 
-- 
2.30.1 (Apple Git-130)



More information about the busybox mailing list