X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fmanager.c;h=d33112df2f3699af4db9c3a5a812bd97c6c578e8;hb=496068a8288084ab3ecf8b179a8403ecff1a6be8;hp=e53f22215de0ef6566f3112a8aec941b9f940386;hpb=e801700e9acdde60078eb1d41b41b06369b83541;p=elogind.git
diff --git a/src/core/manager.c b/src/core/manager.c
index e53f22215..d33112df2 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -19,7 +19,6 @@
along with systemd; If not, see .
***/
-#include
#include
#include
#include
@@ -27,14 +26,10 @@
#include
#include
#include
-#include
#include
#include
#include
-#include
#include
-#include
-#include
#include
#include
@@ -43,7 +38,6 @@
#endif
#include "sd-daemon.h"
-#include "sd-id128.h"
#include "sd-messages.h"
#include "manager.h"
@@ -56,7 +50,6 @@
#include "mkdir.h"
#include "ratelimit.h"
#include "locale-setup.h"
-#include "mount-setup.h"
#include "unit-name.h"
#include "missing.h"
#include "path-lookup.h"
@@ -64,7 +57,6 @@
#include "exit-status.h"
#include "virt.h"
#include "watchdog.h"
-#include "cgroup-util.h"
#include "path-util.h"
#include "audit-fd.h"
#include "boot-timestamps.h"
@@ -84,9 +76,6 @@
#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);
@@ -96,16 +85,16 @@ 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) {
+static void manager_watch_jobs_in_progress(Manager *m) {
usec_t next;
assert(m);
if (m->jobs_in_progress_event_source)
- return 0;
+ return;
next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC;
- return sd_event_add_time(
+ (void) sd_event_add_time(
m->event,
&m->jobs_in_progress_event_source,
CLOCK_MONOTONIC,
@@ -189,8 +178,10 @@ static void manager_print_jobs_in_progress(Manager *m) {
m->jobs_in_progress_iteration++;
- if (m->n_running_jobs > 1)
- asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs);
+ if (m->n_running_jobs > 1) {
+ if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0)
+ job_of_n = NULL;
+ }
format_timespan(time, sizeof(time), now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC);
if (job_get_timeout(j, &x) > 0)
@@ -552,6 +543,9 @@ int manager_new(SystemdRunningAs running_as, bool test_run, Manager **_m) {
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;
@@ -708,7 +702,7 @@ static int manager_setup_kdbus(Manager *m) {
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(
@@ -844,7 +838,8 @@ static unsigned manager_dispatch_gc_queue(Manager *m) {
if (u->gc_marker == gc_marker + GC_OFFSET_BAD ||
u->gc_marker == gc_marker + GC_OFFSET_UNSURE) {
- log_unit_debug(u->id, "Collecting %s", u->id);
+ if (u->id)
+ log_unit_debug(u->id, "Collecting %s", u->id);
u->gc_marker = gc_marker + GC_OFFSET_BAD;
unit_add_to_cleanup_queue(u);
}
@@ -961,7 +956,7 @@ int manager_enumerate(Manager *m) {
int q;
if (unit_vtable[c]->supported && !unit_vtable[c]->supported(m)) {
- log_info("Unit type .%s is not supported on this system.", unit_type_to_string(c));
+ log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
continue;
}
@@ -983,7 +978,28 @@ static int manager_coldplug(Manager *m) {
Unit *u;
char *k;
- assert(m);
+ /*
+ * Some unit types tend to spawn jobs or check other units' state
+ * during coldplug. This is wrong because it is undefined whether the
+ * units in question have been already coldplugged (i. e. their state
+ * restored). This way, we can easily re-start an already started unit
+ * or otherwise make a wrong decision based on the unit's state.
+ *
+ * Solve this by providing a way for coldplug functions to defer
+ * such actions until after all units have been coldplugged.
+ *
+ * We store Unit* -> int(*)(Unit*).
+ *
+ * https://bugs.freedesktop.org/show_bug.cgi?id=88401
+ */
+ _cleanup_hashmap_free_ Hashmap *deferred_work = NULL;
+ int(*proc)(Unit*);
+
+ assert(m);
+
+ deferred_work = hashmap_new(&trivial_hash_ops);
+ if (!deferred_work)
+ return -ENOMEM;
/* Then, let's set up their initial state. */
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
@@ -993,7 +1009,17 @@ static int manager_coldplug(Manager *m) {
if (u->id != k)
continue;
- q = unit_coldplug(u);
+ q = unit_coldplug(u, deferred_work);
+ if (q < 0)
+ r = q;
+ }
+
+ /* After coldplugging and setting up initial state of the units,
+ * let's perform operations which spawn jobs or query units' state. */
+ HASHMAP_FOREACH_KEY(proc, u, deferred_work, i) {
+ int q;
+
+ q = proc(u);
if (q < 0)
r = q;
}
@@ -1521,8 +1547,6 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
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) {
@@ -1726,7 +1750,19 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
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;
}
@@ -2096,8 +2132,7 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
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?
@@ -2215,7 +2250,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
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);
@@ -2675,7 +2710,9 @@ void manager_check_finished(Manager *m) {
if (hashmap_size(m->jobs) > 0) {
if (m->jobs_in_progress_event_source)
- sd_event_source_set_time(m->jobs_in_progress_event_source, now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC);
+ /* Ignore any failure, this is only for feedback */
+ (void) sd_event_source_set_time(m->jobs_in_progress_event_source,
+ now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC);
return;
}
@@ -3052,6 +3089,24 @@ const char *manager_get_runtime_prefix(Manager *m) {
getenv("XDG_RUNTIME_DIR");
}
+void manager_update_failed_units(Manager *m, Unit *u, bool failed) {
+ unsigned size;
+
+ assert(m);
+ assert(u->manager == m);
+
+ size = set_size(m->failed_units);
+
+ if (failed) {
+ if (set_put(m->failed_units, u) < 0)
+ log_oom();
+ } else
+ set_remove(m->failed_units, u);
+
+ if (set_size(m->failed_units) != size)
+ bus_manager_send_change_signal(m);
+}
+
ManagerState manager_state(Manager *m) {
Unit *u;