X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fmanager.c;h=be47766a734d39de237265f3b9a1181ce179ebe1;hp=43460f15913fae58958cf6122d8dfa755326ef5a;hb=1c0f62e37b0e775df7cb6121bc6ae64d1d885d3b;hpb=ac155bb885f9ea8aac3979a6b2686f0c8a9cc6e3 diff --git a/src/manager.c b/src/manager.c index 43460f159..be47766a7 100644 --- a/src/manager.c +++ b/src/manager.c @@ -61,6 +61,7 @@ #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 @@ -247,8 +248,11 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) { 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; @@ -306,15 +310,15 @@ 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++; } @@ -382,7 +386,7 @@ good: } static unsigned manager_dispatch_gc_queue(Manager *m) { - Unit *meta; + Unit *u; unsigned n = 0; unsigned gc_marker; @@ -401,21 +405,21 @@ static unsigned manager_dispatch_gc_queue(Manager *m) { 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); } } @@ -1768,7 +1772,7 @@ Unit *manager_get_unit(Manager *m, const char *name) { } unsigned manager_dispatch_load_queue(Manager *m) { - Unit *meta; + Unit *u; unsigned n = 0; assert(m); @@ -1782,10 +1786,10 @@ unsigned manager_dispatch_load_queue(Manager *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++; } @@ -1929,7 +1933,7 @@ unsigned manager_dispatch_run_queue(Manager *m) { unsigned manager_dispatch_dbus_queue(Manager *m) { Job *j; - Unit *meta; + Unit *u; unsigned n = 0; assert(m); @@ -1939,10 +1943,10 @@ unsigned manager_dispatch_dbus_queue(Manager *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++; } @@ -2430,6 +2434,7 @@ static int process_event(Manager *m, struct epoll_event *ev) { int manager_loop(Manager *m) { int r; + int wait_msec = -1; RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000); @@ -2444,17 +2449,29 @@ int manager_loop(Manager *m) { /* 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) @@ -2478,17 +2495,20 @@ int manager_loop(Manager *m) { 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; } @@ -2940,7 +2960,7 @@ bool manager_is_booting_or_shutting_down(Manager *m) { 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? */