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
|
//kbuild:lib-$(CONFIG_TIMEOUT) += timeout.o
|
||||||
|
|
||||||
//usage:#define timeout_trivial_usage
|
//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:#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.\n"
|
||||||
//usage: "Default SIG: TERM."
|
//usage: "Default SIG: TERM."
|
||||||
|
//usage: "If it still exists in KILL_SECS seconds, send KILL.\n"
|
||||||
|
|
||||||
#include "libbb.h"
|
#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, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int timeout_main(int argc UNUSED_PARAM, char **argv)
|
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 status;
|
||||||
int parent = 0;
|
int parent = 0;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
int kill_timeout;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
char *sv1, *sv2;
|
char *sv1, *sv2;
|
||||||
#endif
|
#endif
|
||||||
const char *opt_s = "TERM";
|
const char *opt_s = "TERM";
|
||||||
|
char *opt_k = NULL;
|
||||||
|
|
||||||
/* -p option is not documented, it is needed to support NOMMU. */
|
/* -p option is not documented, it is needed to support NOMMU. */
|
||||||
|
|
||||||
/* -t SECONDS; -p PARENT_PID */
|
/* -t SECONDS; -p PARENT_PID */
|
||||||
/* '+': stop at first non-option */
|
/* '+': 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! */
|
/*argv += optind; - no, wait for bb_daemonize_or_rexec! */
|
||||||
|
|
||||||
signo = get_signum(opt_s);
|
signo = get_signum(opt_s);
|
||||||
if (signo < 0)
|
if (signo < 0)
|
||||||
bb_error_msg_and_die("unknown signal '%s'", opt_s);
|
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])
|
if (!argv[optind])
|
||||||
bb_show_usage();
|
bb_show_usage();
|
||||||
timeout = parse_duration_str(argv[optind++]);
|
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);
|
bb_daemonize_or_rexec(0, argv);
|
||||||
/* Here we are grandchild. Sleep, then kill grandparent */
|
/* Here we are grandchild. Sleep, then kill grandparent */
|
||||||
grandchild:
|
grandchild:
|
||||||
/* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */
|
if (timeout_wait(timeout, parent) == EXIT_SUCCESS)
|
||||||
while (1) {
|
|
||||||
sleep1();
|
|
||||||
if (--timeout <= 0)
|
|
||||||
break;
|
|
||||||
if (kill(parent, 0)) {
|
|
||||||
/* process is gone */
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
|
||||||
}
|
|
||||||
kill(parent, signo);
|
kill(parent, signo);
|
||||||
|
|
||||||
|
if (kill_timeout > 0) {
|
||||||
|
if (timeout_wait(kill_timeout, parent) == EXIT_SUCCESS)
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
kill(parent, SIGKILL);
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user