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>
This commit is contained in:
parent
c1eac153e8
commit
7d49fedc86
@ -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);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user