#include "fdset.h"
#include "special.h"
#include "conf-parser.h"
-#include "bus-errors.h"
+#include "dbus-common.h"
#include "missing.h"
#include "label.h"
#include "build.h"
#include "env-util.h"
#include "hwclock.h"
#include "sd-daemon.h"
+#include "sd-messages.h"
#include "mount-setup.h"
#include "loopback-setup.h"
#endif
#include "hostname-setup.h"
#include "machine-id-setup.h"
-#include "locale-setup.h"
#include "selinux-setup.h"
#include "ima-setup.h"
#include "fileio.h"
static bool arg_confirm_spawn = false;
static bool arg_show_status = true;
static bool arg_switched_root = false;
-static char **arg_default_controllers = NULL;
static char ***arg_join_controllers = NULL;
static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
static usec_t arg_runtime_watchdog = 0;
static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
+static char **arg_default_environment = NULL;
static struct rlimit *arg_default_rlimit[RLIMIT_NLIMITS] = {};
static uint64_t arg_capability_bounding_set_drop = 0;
static nsec_t arg_timer_slack_nsec = (nsec_t) -1;
_noreturn_ static void crash(int sig) {
- if (!arg_dump_core)
+ if (getpid() != 1)
+ /* Pass this on immediately, if this is not PID 1 */
+ raise(sig);
+ else if (!arg_dump_core)
log_error("Caught <%s>, not dumping core.", signal_to_string(sig));
else {
- struct sigaction sa;
+ struct sigaction sa = {
+ .sa_handler = nop_handler,
+ .sa_flags = SA_NOCLDSTOP|SA_RESTART,
+ };
pid_t pid;
/* We want to wait for the core process, hence let's enable SIGCHLD */
- zero(sa);
- sa.sa_handler = nop_handler;
- sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
- assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
+ sigaction(SIGCHLD, &sa, NULL);
- if ((pid = fork()) < 0)
+ pid = fork();
+ if (pid < 0)
log_error("Caught <%s>, cannot fork for core dump: %s", signal_to_string(sig), strerror(errno));
else if (pid == 0) {
- struct rlimit rl;
+ struct rlimit rl = {};
/* Enable default signal handler for core dump */
zero(sa);
sa.sa_handler = SIG_DFL;
- assert_se(sigaction(sig, &sa, NULL) == 0);
+ sigaction(sig, &sa, NULL);
/* Don't limit the core dump size */
- zero(rl);
rl.rlim_cur = RLIM_INFINITY;
rl.rlim_max = RLIM_INFINITY;
setrlimit(RLIMIT_CORE, &rl);
/* Just to be sure... */
- assert_se(chdir("/") == 0);
+ chdir("/");
/* Raise the signal again */
raise(sig);
int r;
/* Order things nicely. */
- if ((r = wait_for_terminate(pid, &status)) < 0)
+ r = wait_for_terminate(pid, &status);
+ if (r < 0)
log_error("Caught <%s>, waitpid() failed: %s", signal_to_string(sig), strerror(-r));
else if (status.si_code != CLD_DUMPED)
log_error("Caught <%s>, core dump failed.", signal_to_string(sig));
chvt(arg_crash_chvt);
if (arg_crash_shell) {
- struct sigaction sa;
+ struct sigaction sa = {
+ .sa_handler = SIG_IGN,
+ .sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART,
+ };
pid_t pid;
log_info("Executing crash shell in 10s...");
sleep(10);
/* Let the kernel reap children for us */
- zero(sa);
- sa.sa_handler = SIG_IGN;
- sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART;
assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
pid = fork();
}
static void install_crash_handler(void) {
- struct sigaction sa;
-
- zero(sa);
-
- sa.sa_handler = crash;
- sa.sa_flags = SA_NODEFER;
+ struct sigaction sa = {
+ .sa_handler = crash,
+ .sa_flags = SA_NODEFER,
+ };
sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1);
}
arg_default_std_error = r;
} else if (startswith(word, "systemd.setenv=")) {
_cleanup_free_ char *cenv = NULL;
- char *eq;
- int r;
cenv = strdup(word + 15);
if (!cenv)
return -ENOMEM;
- eq = strchr(cenv, '=');
- if (!eq) {
- if (!env_name_is_valid(cenv))
- log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv);
- else {
- r = unsetenv(cenv);
- if (r < 0)
- log_warning("Unsetting environment variable '%s' failed, ignoring: %m", cenv);
- }
- } else {
- if (!env_assignment_is_valid(cenv))
- log_warning("Environment variable assignment '%s' is not valid. Ignoring.", cenv);
- else {
- *eq = 0;
- r = setenv(cenv, eq + 1, 1);
- if (r < 0)
- log_warning("Setting environment variable '%s=%s' failed, ignoring: %m", cenv, eq + 1);
- }
- }
+ if (env_assignment_is_valid(cenv)) {
+ char **env;
+
+ env = strv_env_set(arg_default_environment, cenv);
+ if (env)
+ arg_default_environment = env;
+ else
+ log_warning("Setting environment variable '%s' failed, ignoring: %m", cenv);
+ } else
+ log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv);
} else if (startswith(word, "systemd.") ||
(in_initrd() && startswith(word, "rd.systemd."))) {
} else if (streq(word, "quiet"))
arg_show_status = false;
- else if (!in_initrd()) {
+ else if (streq(word, "debug")) {
+ /* Log to kmsg, the journal socket will fill up before the
+ * journal is started and tools running during that time
+ * will block with every log message for for 60 seconds,
+ * before they give up. */
+ log_set_max_level(LOG_DEBUG);
+ log_set_target(LOG_TARGET_KMSG);
+ } else if (!in_initrd()) {
unsigned i;
/* SysV compatibility */
return 0;
}
-static int config_parse_level2(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- log_set_max_level_from_string(rvalue);
- return 0;
-}
-
-static int config_parse_target(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- log_set_target_from_string(rvalue);
- return 0;
-}
-
-static int config_parse_color(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- log_show_color_from_string(rvalue);
- return 0;
-}
-
-static int config_parse_location(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+#define DEFINE_SETTER(name, func, descr) \
+ static int name(const char *unit, \
+ const char *filename, \
+ unsigned line, \
+ const char *section, \
+ const char *lvalue, \
+ int ltype, \
+ const char *rvalue, \
+ void *data, \
+ void *userdata) { \
+ \
+ int r; \
+ \
+ assert(filename); \
+ assert(lvalue); \
+ assert(rvalue); \
+ \
+ r = func(rvalue); \
+ if (r < 0) \
+ log_syntax(unit, LOG_ERR, filename, line, -r, \
+ "Invalid " descr "'%s': %s", \
+ rvalue, strerror(-r)); \
+ \
+ return 0; \
+ }
- assert(filename);
- assert(lvalue);
- assert(rvalue);
+DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level")
+DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target")
+DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" )
+DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location")
- log_show_location_from_string(rvalue);
- return 0;
-}
-static int config_parse_cpu_affinity2(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+static int config_parse_cpu_affinity2(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
char *w;
size_t l;
return log_oom();
if (r < 0 || cpu >= ncpus) {
- log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, -r,
+ "Failed to parse CPU affinity '%s'", rvalue);
CPU_FREE(c);
return -EBADMSG;
}
if (c) {
if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
- log_warning("Failed to set CPU affinity: %m");
+ log_warning_unit(unit, "Failed to set CPU affinity: %m");
CPU_FREE(c);
}
}
static void free_join_controllers(void) {
- if (!arg_join_controllers)
- return;
-
strv_free_free(arg_join_controllers);
arg_join_controllers = NULL;
}
-static int config_parse_join_controllers(
- const char *filename,
- unsigned line,
- const char *section,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+static int config_parse_join_controllers(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
unsigned n = 0;
char *state, *w;
{ "Manager", "ShowStatus", config_parse_bool, 0, &arg_show_status },
{ "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt },
{ "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
- { "Manager", "DefaultControllers", config_parse_strv, 0, &arg_default_controllers },
{ "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output },
{ "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error },
{ "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
- { "Manager", "RuntimeWatchdogSec", config_parse_usec, 0, &arg_runtime_watchdog },
- { "Manager", "ShutdownWatchdogSec", config_parse_usec, 0, &arg_shutdown_watchdog },
+ { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
+ { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
{ "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop },
{ "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
+ { "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
{ "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU]},
{ "Manager", "DefaultLimitFSIZE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE]},
{ "Manager", "DefaultLimitDATA", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_DATA]},
{ NULL, NULL, NULL, 0, NULL }
};
- FILE *f;
+ _cleanup_fclose_ FILE *f;
const char *fn;
int r;
- fn = arg_running_as == SYSTEMD_SYSTEM ? SYSTEM_CONFIG_FILE : USER_CONFIG_FILE;
+ fn = arg_running_as == SYSTEMD_SYSTEM ? PKGSYSCONFDIR "/system.conf" : PKGSYSCONFDIR "/user.conf";
f = fopen(fn, "re");
if (!f) {
if (errno == ENOENT)
return 0;
}
- r = config_parse(fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, NULL);
+ r = config_parse(NULL, fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, false, NULL);
if (r < 0)
log_warning("Failed to parse configuration file: %s", strerror(-r));
- fclose(f);
-
return 0;
}
static int parse_proc_cmdline(void) {
- char *line, *w, *state;
+ _cleanup_free_ char *line = NULL;
+ char *w, *state;
int r;
size_t l;
if (detect_container(NULL) > 0)
return 0;
- if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
+ r = read_one_line_file("/proc/cmdline", &line);
+ if (r < 0) {
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
return 0;
}
FOREACH_WORD_QUOTED(w, l, line, state) {
- char *word;
+ _cleanup_free_ char *word;
- if (!(word = strndup(w, l))) {
- r = -ENOMEM;
- goto finish;
- }
+ word = strndup(w, l);
+ if (!word)
+ return log_oom();
r = parse_proc_cmdline_word(word);
if (r < 0) {
log_error("Failed on cmdline argument %s: %s", word, strerror(-r));
- free(word);
- goto finish;
+ return r;
}
-
- free(word);
}
- r = 0;
-
-finish:
- free(line);
- return r;
+ return 0;
}
static int parse_argv(int argc, char *argv[]) {
return 0;
}
-static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool serialize_jobs) {
+static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching_root) {
FILE *f = NULL;
FDSet *fds = NULL;
int r;
assert(_f);
assert(_fds);
- /* Make sure nothing is really destructed when we shut down */
- m->n_reloading ++;
-
r = manager_open_serialization(m, &f);
if (r < 0) {
log_error("Failed to create serialization file: %s", strerror(-r));
goto fail;
}
+ /* Make sure nothing is really destructed when we shut down */
+ m->n_reloading ++;
+ bus_broadcast_reloading(m, true);
+
fds = fdset_new();
if (!fds) {
r = -ENOMEM;
goto fail;
}
- r = manager_serialize(m, f, fds, serialize_jobs);
+ r = manager_serialize(m, f, fds, switching_root);
if (r < 0) {
log_error("Failed to serialize state: %s", strerror(-r));
goto fail;
return 0;
}
-static struct dual_timestamp* parse_initrd_timestamp(struct dual_timestamp *t) {
- const char *e;
- unsigned long long a, b;
-
- assert(t);
-
- e = getenv("RD_TIMESTAMP");
- if (!e)
- return NULL;
-
- if (sscanf(e, "%llu %llu", &a, &b) != 2)
- return NULL;
-
- t->realtime = (usec_t) a;
- t->monotonic = (usec_t) b;
-
- return t;
-}
-
static void test_mtab(void) {
char *p;
return -ENOMEM;
arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL);
- if (!arg_join_controllers[0])
- return -ENOMEM;
-
arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL);
- if (!arg_join_controllers[1])
+ arg_join_controllers[2] = NULL;
+
+ if (!arg_join_controllers[0] || !arg_join_controllers[1]) {
+ free_join_controllers();
return -ENOMEM;
+ }
- arg_join_controllers[2] = NULL;
return 0;
}
bool reexecute = false;
const char *shutdown_verb = NULL;
dual_timestamp initrd_timestamp = { 0ULL, 0ULL };
+ dual_timestamp userspace_timestamp = { 0ULL, 0ULL };
+ dual_timestamp kernel_timestamp = { 0ULL, 0ULL };
static char systemd[] = "systemd";
bool skip_setup = false;
int j;
}
#endif
+ dual_timestamp_from_monotonic(&kernel_timestamp, 0);
+ dual_timestamp_get(&userspace_timestamp);
+
/* Determine if this is a reexecution or normal bootup. We do
* the full command line parsing much later, so let's just
* have a quick peek here. */
- for (j = 1; j < argc; j++)
- if (streq(argv[j], "--deserialize")) {
- skip_setup = true;
- break;
- }
+ if (strv_find(argv+1, "--deserialize"))
+ skip_setup = true;
/* If we have switched root, do all the special setup
* things */
- for (j = 1; j < argc; j++)
- if (streq(argv[j], "--switched-root")) {
- skip_setup = false;
- break;
- }
+ if (strv_find(argv+1, "--switched-root"))
+ skip_setup = false;
/* If we get started via the /sbin/init symlink then we are
called 'init'. After a subsequent reexecution we are then
log_set_target(LOG_TARGET_KMSG);
log_open();
- if (in_initrd()) {
- char *rd_timestamp = NULL;
-
- dual_timestamp_get(&initrd_timestamp);
- asprintf(&rd_timestamp, "%llu %llu",
- (unsigned long long) initrd_timestamp.realtime,
- (unsigned long long) initrd_timestamp.monotonic);
- if (rd_timestamp) {
- setenv("RD_TIMESTAMP", rd_timestamp, 1);
- free(rd_timestamp);
- }
- }
+ if (in_initrd())
+ initrd_timestamp = userspace_timestamp;
if (!skip_setup) {
mount_setup_early();
*/
hwclock_reset_timezone();
- /* Tell the kernel our time zone */
+ /* Tell the kernel our timezone */
r = hwclock_set_timezone(NULL);
if (r < 0)
- log_error("Failed to set the kernel's time zone, ignoring: %s", strerror(-r));
+ log_error("Failed to set the kernel's timezone, ignoring: %s", strerror(-r));
}
}
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
} else if (getpid() == 1) {
-
/* Running inside a container, as PID 1 */
arg_running_as = SYSTEMD_SYSTEM;
log_set_target(LOG_TARGET_CONSOLE);
/* For the later on, see above... */
log_set_target(LOG_TARGET_JOURNAL);
- } else {
+ /* clear the kernel timestamp,
+ * because we are in a container */
+ kernel_timestamp.monotonic = 0ULL;
+ kernel_timestamp.realtime = 0ULL;
+ } else {
/* Running as user instance */
arg_running_as = SYSTEMD_USER;
log_set_target(LOG_TARGET_AUTO);
log_open();
+
+ /* clear the kernel timestamp,
+ * because we are not PID 1 */
+ kernel_timestamp.monotonic = 0ULL;
+ kernel_timestamp.realtime = 0ULL;
}
/* Initialize default unit */
/* Mount /proc, /sys and friends, so that /proc/cmdline and
* /proc/$PID/fd is available. */
- if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
+ if (getpid() == 1) {
r = mount_setup(loaded_policy);
if (r < 0)
goto finish;
/* Reset all signal handlers. */
assert_se(reset_all_signal_handlers() == 0);
- /* If we are init, we can block sigkill. Yay. */
ignore_signals(SIGNALS_IGNORE, -1);
if (parse_config_file() < 0)
if (serialization)
assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
- /* Set up PATH unless it is already set */
- setenv("PATH",
-#ifdef HAVE_SPLIT_USR
- "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
-#else
- "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
-#endif
- arg_running_as == SYSTEMD_SYSTEM);
-
- if (arg_running_as == SYSTEMD_SYSTEM) {
- /* Parse the data passed to us. We leave this
- * variables set, but the manager later on will not
- * pass them on to our children. */
- if (!in_initrd())
- parse_initrd_timestamp(&initrd_timestamp);
-
- /* Unset some environment variables passed in from the
- * kernel that don't really make sense for us. */
- unsetenv("HOME");
- unsetenv("TERM");
-
- /* When we are invoked by a shell, these might be set,
- * but make little sense to pass on */
- unsetenv("PWD");
- unsetenv("SHLVL");
- unsetenv("_");
-
- /* When we are invoked by a chroot-like tool such as
- * nspawn, these might be set, but make little sense
- * to pass on */
- unsetenv("USER");
- unsetenv("LOGNAME");
-
- /* We suppress the socket activation env vars, as
- * we'll try to match *any* open fd to units if
- * possible. */
- unsetenv("LISTEN_FDS");
- unsetenv("LISTEN_PID");
-
- /* All other variables are left as is, so that clients
- * can still read them via /proc/1/environ */
- }
-
- /* Move out of the way, so that we won't block unmounts */
- assert_se(chdir("/") == 0);
-
if (arg_running_as == SYSTEMD_SYSTEM) {
/* Become a session leader if we aren't one yet. */
setsid();
umask(0);
}
+ /* Move out of the way, so that we won't block unmounts */
+ assert_se(chdir("/") == 0);
+
/* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
dbus_connection_set_change_sigpipe(FALSE);
/* Make sure we leave a core dump without panicing the
* kernel. */
- if (getpid() == 1)
+ if (getpid() == 1) {
install_crash_handler();
- if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
r = mount_cgroup_controllers(arg_join_controllers);
if (r < 0)
goto finish;
log_debug(PACKAGE_STRING " running in user mode. (" SYSTEMD_FEATURES ")");
if (arg_running_as == SYSTEMD_SYSTEM && !skip_setup) {
- locale_setup();
-
if (arg_show_status || plymouth_running())
status_welcome();
log_error("Failed to adjust timer slack: %m");
if (arg_capability_bounding_set_drop) {
- r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
+ r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
if (r < 0) {
- log_error("Failed to drop capability bounding set: %s", strerror(-r));
+ log_error("Failed to drop capability bounding set of usermode helpers: %s", strerror(-r));
goto finish;
}
- r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
+ r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
if (r < 0) {
- log_error("Failed to drop capability bounding set of usermode helpers: %s", strerror(-r));
+ log_error("Failed to drop capability bounding set: %s", strerror(-r));
goto finish;
}
}
if (arg_running_as == SYSTEMD_SYSTEM)
bump_rlimit_nofile(&saved_rlimit_nofile);
- r = manager_new(arg_running_as, &m);
+ r = manager_new(arg_running_as, !!serialization, &m);
if (r < 0) {
log_error("Failed to allocate manager object: %s", strerror(-r));
goto finish;
m->default_std_error = arg_default_std_error;
m->runtime_watchdog = arg_runtime_watchdog;
m->shutdown_watchdog = arg_shutdown_watchdog;
+ m->userspace_timestamp = userspace_timestamp;
+ m->kernel_timestamp = kernel_timestamp;
+ m->initrd_timestamp = initrd_timestamp;
manager_set_default_rlimits(m, arg_default_rlimit);
- if (dual_timestamp_is_set(&initrd_timestamp))
- m->initrd_timestamp = initrd_timestamp;
-
- if (arg_default_controllers)
- manager_set_default_controllers(m, arg_default_controllers);
+ if (arg_default_environment)
+ manager_environment_add(m, arg_default_environment);
manager_set_show_status(m, arg_show_status);
if (r < 0) {
log_error("Failed to load default target: %s", bus_error(&error, r));
dbus_error_free(&error);
- } else if (target->load_state == UNIT_ERROR)
+ } else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND)
log_error("Failed to load default target: %s", strerror(-target->load_error));
else if (target->load_state == UNIT_MASKED)
log_error("Default target masked.");
log_error("Failed to load rescue target: %s", bus_error(&error, r));
dbus_error_free(&error);
goto finish;
- } else if (target->load_state == UNIT_ERROR) {
+ } else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND) {
log_error("Failed to load rescue target: %s", strerror(-target->load_error));
goto finish;
} else if (target->load_state == UNIT_MASKED) {
r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, false, &error, &default_unit_job);
if (r == -EPERM) {
- log_error("Default target could not be isolated, starting instead: %s", bus_error(&error, r));
+ log_debug("Default target could not be isolated, starting instead: %s", bus_error(&error, r));
dbus_error_free(&error);
r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
after_startup = now(CLOCK_MONOTONIC);
log_full(arg_action == ACTION_TEST ? LOG_INFO : LOG_DEBUG,
"Loaded units and determined initial transaction in %s.",
- format_timespan(timespan, sizeof(timespan), after_startup - before_startup));
+ format_timespan(timespan, sizeof(timespan), after_startup - before_startup, 0));
if (arg_action == ACTION_TEST) {
printf("-> By jobs:\n");
case MANAGER_REEXECUTE:
- if (prepare_reexecute(m, &serialization, &fds, true) < 0)
+ if (prepare_reexecute(m, &serialization, &fds, false) < 0)
goto finish;
reexecute = true;
m->switch_root = m->switch_root_init = NULL;
if (!switch_root_init)
- if (prepare_reexecute(m, &serialization, &fds, false) < 0)
+ if (prepare_reexecute(m, &serialization, &fds, true) < 0)
goto finish;
reexecute = true;
free(arg_default_rlimit[j]);
free(arg_default_unit);
- strv_free(arg_default_controllers);
free_join_controllers();
dbus_shutdown();
args[i++] = sfd;
args[i++] = NULL;
+ /* do not pass along the environment we inherit from the kernel or initrd */
+ if (switch_root_dir)
+ clearenv();
+
assert(i <= args_size);
execv(args[0], (char* const*) args);
}
watchdog_close(true);
}
+ /* Avoid the creation of new processes forked by the
+ * kernel; at this point, we will not listen to the
+ * signals anyway */
+ if (detect_container(NULL) <= 0)
+ cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
+
execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
free(env_block);
log_error("Failed to execute shutdown binary, freezing: %m");