#define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3)
#define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3
-#define NOTIFY_FD_MAX 768
-#define NOTIFY_BUFFER_MAX PIPE_BUF
-
static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
static int manager_dispatch_run_queue(sd_event_source *source, void *userdata);
+static int manager_run_generators(Manager *m);
+static void manager_undo_generators(Manager *m);
static int manager_watch_jobs_in_progress(Manager *m) {
usec_t next;
m->test_run = test_run;
+ /* Reboot immediately if the user hits C-A-D more often than 7x per 2s */
+ RATELIMIT_INIT(m->ctrl_alt_del_ratelimit, 2 * USEC_PER_SEC, 7);
+
r = manager_default_environment(m);
if (r < 0)
goto fail;
if (m->test_run || m->kdbus_fd >= 0)
return 0;
- if (getpid() == 1)
+ if (m->running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0)
bus_kernel_fix_attach_mask();
m->kdbus_fd = bus_kernel_create_bus(
assert(m);
dual_timestamp_get(&m->generators_start_timestamp);
- manager_run_generators(m);
+ r = manager_run_generators(m);
dual_timestamp_get(&m->generators_finish_timestamp);
+ if (r < 0)
+ return r;
r = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
return -errno;
}
- if (n == 0)
- return -ECONNRESET;
for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
case SIGINT:
if (m->running_as == SYSTEMD_SYSTEM) {
- manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
+
+ /* If the user presses C-A-D more than
+ * 7 times within 2s, we reboot
+ * immediately. */
+
+ if (ratelimit_test(&m->ctrl_alt_del_ratelimit))
+ manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
+ else {
+ log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately.");
+ status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately.");
+ m->exit_code = MANAGER_REBOOT;
+ }
+
break;
}
return;
}
- msg = strappenda("unit=", p);
-
+ msg = strjoina("unit=", p);
if (audit_log_user_comm_message(audit_fd, type, msg, "systemd", NULL, NULL, NULL, success) < 0) {
if (errno == EPERM)
/* We aren't allowed to send audit messages?
m->n_reloading ++;
- fprintf(f, "current-job-id=%i\n", m->current_job_id);
+ fprintf(f, "current-job-id=%"PRIu32"\n", m->current_job_id);
fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs);
fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs);
lookup_paths_free(&m->lookup_paths);
/* Find new unit paths */
- manager_run_generators(m);
+ q = manager_run_generators(m);
+ if (q < 0 && r >= 0)
+ r = q;
q = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
m->generator_unit_path,
m->generator_unit_path_early,
m->generator_unit_path_late);
- if (q < 0)
+ if (q < 0 && r >= 0)
r = q;
manager_build_unit_path_cache(m);
/* First, enumerate what we can from all config files */
q = manager_enumerate(m);
- if (q < 0)
+ if (q < 0 && r >= 0)
r = q;
/* Second, deserialize our stored data */
q = manager_deserialize(m, f, fds);
- if (q < 0)
+ if (q < 0 && r >= 0)
r = q;
fclose(f);
/* Re-register notify_fd as event source */
q = manager_setup_notify(m);
- if (q < 0)
+ if (q < 0 && r >= 0)
r = q;
/* Third, fire things up! */
q = manager_coldplug(m);
- if (q < 0)
+ if (q < 0 && r >= 0)
r = q;
assert(m->n_reloading > 0);
return;
}
-void manager_run_generators(Manager *m) {
- _cleanup_closedir_ DIR *d = NULL;
- const char *generator_path;
+static int manager_run_generators(Manager *m) {
+ _cleanup_free_ char **paths = NULL;
const char *argv[5];
+ char **path;
int r;
assert(m);
if (m->test_run)
- return;
+ return 0;
- generator_path = m->running_as == SYSTEMD_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
- d = opendir(generator_path);
- if (!d) {
- if (errno == ENOENT)
- return;
+ paths = generator_paths(m->running_as);
+ if (!paths)
+ return log_oom();
- log_error_errno(errno, "Failed to enumerate generator directory %s: %m",
- generator_path);
- return;
+ /* Optimize by skipping the whole process by not creating output directories
+ * if no generators are found. */
+ STRV_FOREACH(path, paths) {
+ r = access(*path, F_OK);
+ if (r == 0)
+ goto found;
+ if (errno != ENOENT)
+ log_warning_errno(errno, "Failed to open generator directory %s: %m", *path);
}
+ return 0;
+ found:
r = create_generator_dir(m, &m->generator_unit_path, "generator");
if (r < 0)
goto finish;
argv[4] = NULL;
RUN_WITH_UMASK(0022)
- execute_directory(generator_path, d, DEFAULT_TIMEOUT_USEC, (char**) argv);
+ execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, (char**) argv);
finish:
trim_generator_dir(m, &m->generator_unit_path);
trim_generator_dir(m, &m->generator_unit_path_early);
trim_generator_dir(m, &m->generator_unit_path_late);
+ return r;
}
static void remove_generator_dir(Manager *m, char **generator) {
*generator = NULL;
}
-void manager_undo_generators(Manager *m) {
+static void manager_undo_generators(Manager *m) {
assert(m);
remove_generator_dir(m, &m->generator_unit_path);