#include "bus-kernel.h"
#include "time-util.h"
-/* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
-#define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
-
/* Initial delay and the interval for printing status messages about running jobs */
#define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
#define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3)
if (job_get_timeout(j, &x) > 0)
format_timespan(limit, sizeof(limit), x - j->begin_usec, 1*USEC_PER_SEC);
- manager_status_printf(m, true, cylon,
+ manager_status_printf(m, STATUS_TYPE_EPHEMERAL, cylon,
"%sA %s job is running for %s (%s / %s)",
strempty(job_of_n),
job_type_to_string(j->type),
assert(m);
- if (m->test_run)
- return 0;
-
assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
/* We make liberal use of realtime signals here. On
if (!m->notify_socket)
return log_oom();
+ (void) mkdir_parents_label(m->notify_socket, 0755);
+ (void) unlink(m->notify_socket);
+
strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1);
r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
if (r < 0) {
log_error("bind(%s) failed: %m", sa.un.sun_path);
- if (errno == EADDRINUSE) {
- log_notice("Removing %s socket and trying again.", m->notify_socket);
- r = unlink(m->notify_socket);
- if (r < 0) {
- log_error("Failed to remove %s: %m", m->notify_socket);
- return -EADDRINUSE;
- }
-
- r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
- if (r < 0) {
- log_error("bind(%s) failed: %m", sa.un.sun_path);
- return -errno;
- }
- } else
- return -errno;
+ return -errno;
}
r = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
}
log_debug("Successfully set up kdbus on %s", p);
-
- /* Create the namespace directory here, so that the contents
- * of that directory is not visible to non-root users. This is
- * necessary to ensure that users cannot get access to busses
- * of virtualized users when no UID namespacing is used. */
- if (m->running_as == SYSTEMD_SYSTEM)
- mkdir_p_label("/dev/kdbus/domain", 0700);
#endif
return 0;
m->n_running_jobs = 0;
}
-void manager_free(Manager *m) {
+Manager* manager_free(Manager *m) {
UnitType c;
int i;
- assert(m);
+ if (!m)
+ return NULL;
manager_clear_jobs_and_units(m);
hashmap_free(m->units_requiring_mounts_for);
free(m);
+ return NULL;
}
int manager_enumerate(Manager *m) {
assert(unit);
assert(mode < _JOB_MODE_MAX);
- if (mode == JOB_ISOLATE && type != JOB_START) {
- sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
- return -EINVAL;
- }
+ if (mode == JOB_ISOLATE && type != JOB_START)
+ return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
- if (mode == JOB_ISOLATE && !unit->allow_isolate) {
- sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
- return -EPERM;
- }
+ if (mode == JOB_ISOLATE && !unit->allow_isolate)
+ return sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
log_debug_unit(unit->id,
"Trying to enqueue job %s/%s/%s", unit->id,
#ifdef HAVE_AUDIT
_cleanup_free_ char *p = NULL;
+ const char *msg;
int audit_fd;
audit_fd = get_audit_fd();
p = unit_name_to_prefix_and_instance(u->id);
if (!p) {
- log_error_unit(u->id,
- "Failed to allocate unit name for audit message: %s", strerror(ENOMEM));
+ log_oom();
return;
}
- if (audit_log_user_comm_message(audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
- if (errno == EPERM) {
+ msg = strappenda("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?
* Then let's not retry again. */
close_audit_fd();
- } else
+ else
log_warning("Failed to send audit message: %m");
}
#endif
m->kdbus_fd = fdset_remove(fds, fd);
}
- } else if (bus_track_deserialize_item(&m->deserialized_subscribed, l) == 0)
+ } else if (bus_track_deserialize_item(&m->deserialized_subscribed, l) < 0)
log_warning("Unknown serialization item '%s'", l);
}
return unit_inactive_or_pending(u);
}
-void manager_check_finished(Manager *m) {
+static void manager_notify_finished(Manager *m) {
char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec;
- Unit *u = NULL;
- Iterator i;
-
- assert(m);
-
- if (m->n_running_jobs == 0)
- m->jobs_in_progress_event_source = sd_event_source_unref(m->jobs_in_progress_event_source);
-
- 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);
-
- return;
- }
-
- manager_flip_auto_status(m, false);
-
- /* Notify Type=idle units that we are done now */
- m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
- manager_close_idle_pipe(m);
-
- /* Turn off confirm spawn now */
- m->confirm_spawn = false;
-
- /* No need to update ask password status when we're going non-interactive */
- manager_close_ask_password(m);
-
- /* This is no longer the first boot */
- manager_set_first_boot(m, false);
- if (dual_timestamp_is_set(&m->finish_timestamp))
+ if (m->test_run)
return;
- dual_timestamp_get(&m->finish_timestamp);
-
if (m->running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0) {
/* Note that m->kernel_usec.monotonic is always at 0,
NULL);
}
- SET_FOREACH(u, m->startup_units, i)
- if (u->cgroup_path)
- cgroup_context_apply(unit_get_cgroup_context(u), unit_get_cgroup_mask(u), u->cgroup_path, manager_state(m));
-
bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
sd_notifyf(false,
format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC));
}
+void manager_check_finished(Manager *m) {
+ Unit *u = NULL;
+ Iterator i;
+
+ assert(m);
+
+ if (m->n_running_jobs == 0)
+ m->jobs_in_progress_event_source = sd_event_source_unref(m->jobs_in_progress_event_source);
+
+ 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);
+
+ return;
+ }
+
+ manager_flip_auto_status(m, false);
+
+ /* Notify Type=idle units that we are done now */
+ m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
+ manager_close_idle_pipe(m);
+
+ /* Turn off confirm spawn now */
+ m->confirm_spawn = false;
+
+ /* No need to update ask password status when we're going non-interactive */
+ manager_close_ask_password(m);
+
+ /* This is no longer the first boot */
+ manager_set_first_boot(m, false);
+
+ if (dual_timestamp_is_set(&m->finish_timestamp))
+ return;
+
+ dual_timestamp_get(&m->finish_timestamp);
+
+ manager_notify_finished(m);
+
+ SET_FOREACH(u, m->startup_units, i)
+ if (u->cgroup_path)
+ cgroup_context_apply(unit_get_cgroup_context(u), unit_get_cgroup_mask(u), u->cgroup_path, manager_state(m));
+}
+
static int create_generator_dir(Manager *m, char **generator, const char *name) {
char *p;
int r;
unlink("/run/systemd/show-status");
}
-static bool manager_get_show_status(Manager *m) {
+static bool manager_get_show_status(Manager *m, StatusType type) {
assert(m);
if (m->running_as != SYSTEMD_SYSTEM)
return false;
/* If we cannot find out the status properly, just proceed. */
- if (manager_check_ask_password(m) > 0)
+ if (type != STATUS_TYPE_EMERGENCY && manager_check_ask_password(m) > 0)
return false;
if (m->show_status > 0)
unlink("/run/systemd/first-boot");
}
-void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) {
+void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) {
va_list ap;
- if (!manager_get_show_status(m))
+ if (!manager_get_show_status(m, type))
return;
/* XXX We should totally drop the check for ephemeral here
* and thus effectively make 'Type=idle' pointless. */
- if (ephemeral && m->n_on_console > 0)
+ if (type == STATUS_TYPE_EPHEMERAL && m->n_on_console > 0)
return;
va_start(ap, format);
- status_vprintf(status, true, ephemeral, format, ap);
+ status_vprintf(status, true, type == STATUS_TYPE_EPHEMERAL, format, ap);
va_end(ap);
}