#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_SEC 5
-#define JOBS_IN_PROGRESS_PERIOD_SEC 1
+#define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
+#define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3)
#define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3
/* Where clients shall send notification messages to */
if (m->jobs_in_progress_event_source)
return 0;
- return sd_event_add_monotonic(m->event, JOBS_IN_PROGRESS_WAIT_SEC, 0, manager_dispatch_jobs_in_progress, m, &m->jobs_in_progress_event_source);
+ return sd_event_add_monotonic(m->event, now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC, 0, manager_dispatch_jobs_in_progress, m, &m->jobs_in_progress_event_source);
}
#define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1))
}
}
+void manager_flip_auto_status(Manager *m, bool enable) {
+ if (enable) {
+ if (m->show_status == SHOW_STATUS_AUTO)
+ manager_set_show_status(m, SHOW_STATUS_TEMPORARY);
+ } else {
+ if (m->show_status == SHOW_STATUS_TEMPORARY)
+ manager_set_show_status(m, SHOW_STATUS_AUTO);
+ }
+}
+
static void manager_print_jobs_in_progress(Manager *m) {
_cleanup_free_ char *job_of_n = NULL;
Iterator i;
unsigned counter = 0, print_nr;
char cylon[6 + CYLON_BUFFER_EXTRA + 1];
unsigned cylon_pos;
+ char time[FORMAT_TIMESPAN_MAX], limit[FORMAT_TIMESPAN_MAX] = "no limit";
+ uint64_t x;
assert(m);
+ manager_flip_auto_status(m, true);
+
print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs;
HASHMAP_FOREACH(j, m->jobs, i)
cylon_pos = 14 - cylon_pos;
draw_cylon(cylon, sizeof(cylon), 6, cylon_pos);
+ m->jobs_in_progress_iteration++;
+
if (m->n_running_jobs > 1)
if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0)
job_of_n = NULL;
- manager_status_printf(m, true, cylon, "%sA %s job is running for %s",
- strempty(job_of_n), job_type_to_string(j->type), unit_description(j->unit));
+ format_timespan(time, sizeof(time), now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC);
+ 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,
+ "%sA %s job is running for %s (%s / %s)",
+ strempty(job_of_n),
+ job_type_to_string(j->type),
+ unit_description(j->unit),
+ time, limit);
- m->jobs_in_progress_iteration++;
}
static int manager_watch_idle_pipe(Manager *m) {
return 0;
}
+static void manager_clean_environment(Manager *m) {
+ assert(m);
+
+ /* Let's remove some environment variables that we
+ * need ourselves to communicate with our clients */
+ strv_env_unset_many(
+ m->environment,
+ "NOTIFY_SOCKET",
+ "MAINPID",
+ "MANAGERPID",
+ "LISTEN_PID",
+ "LISTEN_FDS",
+ "WATCHDOG_PID",
+ "WATCHDOG_USEC",
+ NULL);
+}
+
static int manager_default_environment(Manager *m) {
assert(m);
/* Import locale variables LC_*= from configuration */
locale_setup(&m->environment);
- } else
+ } else {
/* The user manager passes its own environment
* along to its children. */
m->environment = strv_copy(environ);
+ }
if (!m->environment)
return -ENOMEM;
+ manager_clean_environment(m);
strv_sort(m->environment);
return 0;
case 20:
log_debug("Enabling showing of status.");
- manager_set_show_status(m, true);
+ manager_set_show_status(m, SHOW_STATUS_YES);
break;
case 21:
log_debug("Disabling showing of status.");
- manager_set_show_status(m, false);
+ manager_set_show_status(m, SHOW_STATUS_NO);
break;
case 22:
static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) {
Manager *m = userdata;
+ int r;
+ uint64_t next;
assert(m);
+ assert(source);
manager_print_jobs_in_progress(m);
- return 0;
+
+ next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_PERIOD_USEC;
+ r = sd_event_source_set_time(source, next);
+ if (r < 0)
+ return r;
+
+ return sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
}
int manager_loop(Manager *m) {
}
int manager_open_serialization(Manager *m, FILE **_f) {
- _cleanup_free_ char *path = NULL;
+ const char *path;
int fd = -1;
FILE *f;
assert(_f);
- if (m->running_as == SYSTEMD_SYSTEM)
- asprintf(&path, "/run/systemd/dump-"PID_FMT"-XXXXXX", getpid());
- else
- asprintf(&path, "/tmp/systemd-dump-"PID_FMT"-XXXXXX", getpid());
-
- if (!path)
- return -ENOMEM;
-
- RUN_WITH_UMASK(0077) {
- fd = mkostemp(path, O_RDWR|O_CLOEXEC);
- }
-
+ path = m->running_as == SYSTEMD_SYSTEM ? "/run/systemd" : "/tmp";
+ fd = open_tmpfile(path, O_RDWR|O_CLOEXEC);
if (fd < 0)
return -errno;
- unlink(path);
log_debug("Serializing state to %s", path);
f = fdopen(fd, "w+");
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, JOBS_IN_PROGRESS_PERIOD_SEC);
+ if (m->jobs_in_progress_event_source) {
+ uint64_t next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_PERIOD_USEC;
+ sd_event_source_set_time(m->jobs_in_progress_event_source, next);
+ }
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);
if (b != l)
strv_free(b);
- m->environment = strv_sort(l);
+ m->environment = l;
+ manager_clean_environment(m);
+ strv_sort(m->environment);
+
return 0;
}
log_open();
}
-void manager_set_show_status(Manager *m, bool b) {
+void manager_set_show_status(Manager *m, ShowStatus mode) {
assert(m);
+ assert(IN_SET(mode, SHOW_STATUS_AUTO, SHOW_STATUS_NO, SHOW_STATUS_YES, SHOW_STATUS_TEMPORARY));
if (m->running_as != SYSTEMD_SYSTEM)
return;
- m->show_status = b;
+ m->show_status = mode;
- if (b)
+ if (mode > 0)
touch("/run/systemd/show-status");
else
unlink("/run/systemd/show-status");
if (m->no_console_output)
return false;
- if (m->show_status)
+ if (m->show_status > 0)
return true;
/* If Plymouth is running make sure we show the status, so