#include "bus-errors.h"
#include "exit-status.h"
#include "virt.h"
+#include "watchdog.h"
/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
#define GC_QUEUE_ENTRIES_MAX 16
if (!(m->environment = strv_copy(environ)))
goto fail;
- if (!(m->default_controllers = strv_new("cpu", NULL)))
- goto fail;
+ if (running_as == MANAGER_SYSTEM) {
+ m->default_controllers = strv_new("cpu", NULL);
+ if (!m->default_controllers)
+ goto fail;
+ }
if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
goto fail;
}
static unsigned manager_dispatch_cleanup_queue(Manager *m) {
- Unit *meta;
+ Unit *u;
unsigned n = 0;
assert(m);
- while ((meta = m->cleanup_queue)) {
- assert(meta->in_cleanup_queue);
+ while ((u = m->cleanup_queue)) {
+ assert(u->in_cleanup_queue);
- unit_free((Unit*) meta);
+ unit_free(u);
n++;
}
}
static unsigned manager_dispatch_gc_queue(Manager *m) {
- Unit *meta;
+ Unit *u;
unsigned n = 0;
unsigned gc_marker;
gc_marker = m->gc_marker;
- while ((meta = m->gc_queue)) {
- assert(meta->in_gc_queue);
+ while ((u = m->gc_queue)) {
+ assert(u->in_gc_queue);
- unit_gc_sweep((Unit*) meta, gc_marker);
+ unit_gc_sweep(u, gc_marker);
- LIST_REMOVE(Unit, gc_queue, m->gc_queue, meta);
- meta->in_gc_queue = false;
+ LIST_REMOVE(Unit, gc_queue, m->gc_queue, u);
+ u->in_gc_queue = false;
n++;
- if (meta->gc_marker == gc_marker + GC_OFFSET_BAD ||
- meta->gc_marker == gc_marker + GC_OFFSET_UNSURE) {
- log_debug("Collecting %s", meta->id);
- meta->gc_marker = gc_marker + GC_OFFSET_BAD;
- unit_add_to_cleanup_queue((Unit*) meta);
+ if (u->gc_marker == gc_marker + GC_OFFSET_BAD ||
+ u->gc_marker == gc_marker + GC_OFFSET_UNSURE) {
+ log_debug("Collecting %s", u->id);
+ u->gc_marker = gc_marker + GC_OFFSET_BAD;
+ unit_add_to_cleanup_queue(u);
}
}
}
unsigned manager_dispatch_load_queue(Manager *m) {
- Unit *meta;
+ Unit *u;
unsigned n = 0;
assert(m);
/* Dispatches the load queue. Takes a unit from the queue and
* tries to load its data until the queue is empty */
- while ((meta = m->load_queue)) {
- assert(meta->in_load_queue);
+ while ((u = m->load_queue)) {
+ assert(u->in_load_queue);
- unit_load((Unit*) meta);
+ unit_load(u);
n++;
}
unsigned manager_dispatch_dbus_queue(Manager *m) {
Job *j;
- Unit *meta;
+ Unit *u;
unsigned n = 0;
assert(m);
m->dispatching_dbus_queue = true;
- while ((meta = m->dbus_unit_queue)) {
- assert(meta->in_dbus_queue);
+ while ((u = m->dbus_unit_queue)) {
+ assert(u->in_dbus_queue);
- bus_unit_send_change_signal((Unit*) meta);
+ bus_unit_send_change_signal(u);
n++;
}
int manager_loop(Manager *m) {
int r;
+ int wait_msec = -1;
RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000);
/* There might still be some zombies hanging around from
* before we were exec()'ed. Leat's reap them */
- if ((r = manager_dispatch_sigchld(m)) < 0)
+ r = manager_dispatch_sigchld(m);
+ if (r < 0)
return r;
+ /* Sleep for half the watchdog time */
+ if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM) {
+ wait_msec = (int) (m->runtime_watchdog / 2 / USEC_PER_MSEC);
+ if (wait_msec <= 0)
+ wait_msec = 1;
+ }
+
while (m->exit_code == MANAGER_RUNNING) {
struct epoll_event event;
int n;
+ if (wait_msec >= 0)
+ watchdog_ping();
+
if (!ratelimit_test(&rl)) {
/* Yay, something is going seriously wrong, pause a little */
log_warning("Looping too fast. Throttling execution a little.");
sleep(1);
+ continue;
}
if (manager_dispatch_load_queue(m) > 0)
if (swap_dispatch_reload(m) > 0)
continue;
- if ((n = epoll_wait(m->epoll_fd, &event, 1, -1)) < 0) {
+ n = epoll_wait(m->epoll_fd, &event, 1, wait_msec);
+ if (n < 0) {
if (errno == EINTR)
continue;
return -errno;
- }
+ } else if (n == 0)
+ continue;
assert(n == 1);
- if ((r = process_event(m, &event)) < 0)
+ r = process_event(m, &event);
+ if (r < 0)
return r;
}
assert(m);
/* Is the initial job still around? */
- if (manager_get_job(m, 1))
+ if (manager_get_job(m, m->default_unit_job_id))
return true;
/* Is there a job for the shutdown target? */