aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Slowe <foo@mafoo.org.uk>2021-10-09 12:26:40 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2021-12-17 23:11:17 +0100
commit7d49fedc86bec300d22f44f93ec95825320dd1c1 (patch)
tree0bb535177a75500ebc5ecef1a2d07b7c023d838f
parentc1eac153e8b89cfc9d550991735c09bad1579201 (diff)
downloadbusybox-w32-7d49fedc86bec300d22f44f93ec95825320dd1c1.tar.gz
busybox-w32-7d49fedc86bec300d22f44f93ec95825320dd1c1.tar.bz2
busybox-w32-7d49fedc86bec300d22f44f93ec95825320dd1c1.zip
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 @@
39//kbuild:lib-$(CONFIG_TIMEOUT) += timeout.o 39//kbuild:lib-$(CONFIG_TIMEOUT) += timeout.o
40 40
41//usage:#define timeout_trivial_usage 41//usage:#define timeout_trivial_usage
42//usage: "[-s SIG] SECS PROG ARGS" 42//usage: "[-s SIG] [-k KILL_SECS] SECS PROG ARGS"
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 it still exists in KILL_SECS seconds, send KILL.\n"
46 47
47#include "libbb.h" 48#include "libbb.h"
48 49
50static NOINLINE int timeout_wait(int timeout, pid_t pid)
51{
52 /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */
53 while (1) {
54 sleep1();
55 if (--timeout <= 0)
56 break;
57 if (kill(pid, 0)) {
58 /* process is gone */
59 return EXIT_SUCCESS;
60 }
61 }
62 return EXIT_FAILURE;
63}
64
49int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 65int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
50int timeout_main(int argc UNUSED_PARAM, char **argv) 66int timeout_main(int argc UNUSED_PARAM, char **argv)
51{ 67{
@@ -53,23 +69,29 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
53 int status; 69 int status;
54 int parent = 0; 70 int parent = 0;
55 int timeout; 71 int timeout;
72 int kill_timeout;
56 pid_t pid; 73 pid_t pid;
57#if !BB_MMU 74#if !BB_MMU
58 char *sv1, *sv2; 75 char *sv1, *sv2;
59#endif 76#endif
60 const char *opt_s = "TERM"; 77 const char *opt_s = "TERM";
78 char *opt_k = NULL;
61 79
62 /* -p option is not documented, it is needed to support NOMMU. */ 80 /* -p option is not documented, it is needed to support NOMMU. */
63 81
64 /* -t SECONDS; -p PARENT_PID */ 82 /* -t SECONDS; -p PARENT_PID */
65 /* '+': stop at first non-option */ 83 /* '+': stop at first non-option */
66 getopt32(argv, "+s:" USE_FOR_NOMMU("p:+"), &opt_s, &parent); 84 getopt32(argv, "+s:k:" USE_FOR_NOMMU("p:+"), &opt_s, &opt_k, &parent);
67 /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ 85 /*argv += optind; - no, wait for bb_daemonize_or_rexec! */
68 86
69 signo = get_signum(opt_s); 87 signo = get_signum(opt_s);
70 if (signo < 0) 88 if (signo < 0)
71 bb_error_msg_and_die("unknown signal '%s'", opt_s); 89 bb_error_msg_and_die("unknown signal '%s'", opt_s);
72 90
91 kill_timeout = 0;
92 if (opt_k)
93 kill_timeout = parse_duration_str(opt_k);
94
73 if (!argv[optind]) 95 if (!argv[optind])
74 bb_show_usage(); 96 bb_show_usage();
75 timeout = parse_duration_str(argv[optind++]); 97 timeout = parse_duration_str(argv[optind++]);
@@ -103,17 +125,16 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
103 bb_daemonize_or_rexec(0, argv); 125 bb_daemonize_or_rexec(0, argv);
104 /* Here we are grandchild. Sleep, then kill grandparent */ 126 /* Here we are grandchild. Sleep, then kill grandparent */
105 grandchild: 127 grandchild:
106 /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ 128 if (timeout_wait(timeout, parent) == EXIT_SUCCESS)
107 while (1) { 129 return EXIT_SUCCESS;
108 sleep1(); 130 kill(parent, signo);
109 if (--timeout <= 0) 131
110 break; 132 if (kill_timeout > 0) {
111 if (kill(parent, 0)) { 133 if (timeout_wait(kill_timeout, parent) == EXIT_SUCCESS)
112 /* process is gone */
113 return EXIT_SUCCESS; 134 return EXIT_SUCCESS;
114 } 135 kill(parent, SIGKILL);
115 } 136 }
116 kill(parent, signo); 137
117 return EXIT_SUCCESS; 138 return EXIT_SUCCESS;
118 } 139 }
119 140