return true;
}
-static void wait_for_children(Set *pids, sigset_t *mask) {
+static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
usec_t until;
assert(mask);
if (set_isempty(pids))
return;
- until = now(CLOCK_MONOTONIC) + DEFAULT_TIMEOUT_USEC;
+ until = now(CLOCK_MONOTONIC) + timeout;
for (;;) {
struct timespec ts;
int k;
return set_size(pids);
}
-void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup) {
+void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout) {
sigset_t mask, oldmask;
_cleanup_set_free_ Set *pids = NULL;
log_warning_errno(errno, "kill(-1, SIGCONT) failed: %m");
if (wait_for_exit)
- wait_for_children(pids, &mask);
+ wait_for_children(pids, &mask, timeout);
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
}
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup);
+#include "time-util.h"
+
+void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout);
int retval) {
char log_level[DECIMAL_STR_MAX(int) + 1],
- exit_code[DECIMAL_STR_MAX(uint8_t) + 1];
+ exit_code[DECIMAL_STR_MAX(uint8_t) + 1],
+ timeout[DECIMAL_STR_MAX(usec_t) + 1];
- const char* command_line[11] = {
+ const char* command_line[13] = {
SYSTEMD_SHUTDOWN_BINARY_PATH,
shutdown_verb,
+ "--timeout", timeout,
"--log-level", log_level,
"--log-target",
};
_cleanup_strv_free_ char **env_block = NULL;
- size_t pos = 5;
+ size_t pos = 7;
int r;
assert(shutdown_verb);
env_block = strv_copy(environ);
xsprintf(log_level, "%d", log_get_max_level());
+ xsprintf(timeout, "%" PRI_USEC "us", arg_default_timeout_stop_usec);
switch (log_get_target()) {
if (switch_root_dir) {
/* Kill all remaining processes from the initrd, but don't wait for them, so that we can handle the
* SIGCHLD for them after deserializing. */
- broadcast_signal(SIGTERM, false, true);
+ broadcast_signal(SIGTERM, false, true, arg_default_timeout_stop_usec);
/* And switch root with MS_MOVE, because we remove the old directory afterwards and detach it. */
r = switch_root(switch_root_dir, "/mnt", true, MS_MOVE);
static char* arg_verb;
static uint8_t arg_exit_code;
+static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_LOG_COLOR,
ARG_LOG_LOCATION,
ARG_EXIT_CODE,
+ ARG_TIMEOUT,
};
static const struct option options[] = {
{ "log-color", optional_argument, NULL, ARG_LOG_COLOR },
{ "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
{ "exit-code", required_argument, NULL, ARG_EXIT_CODE },
+ { "timeout", required_argument, NULL, ARG_TIMEOUT },
{}
};
break;
+ case ARG_TIMEOUT:
+ r = parse_sec(optarg, &arg_timeout);
+ if (r < 0)
+ log_error("Failed to parse shutdown timeout %s, ignoring", optarg);
+
+ break;
+
case '\001':
if (!arg_verb)
arg_verb = optarg;
disable_core_dumps();
log_info("Sending SIGTERM to remaining processes...");
- broadcast_signal(SIGTERM, true, true);
+ broadcast_signal(SIGTERM, true, true, arg_timeout);
log_info("Sending SIGKILL to remaining processes...");
- broadcast_signal(SIGKILL, true, false);
+ broadcast_signal(SIGKILL, true, false, arg_timeout);
need_umount = !in_container;
need_swapoff = !in_container;