summaryrefslogtreecommitdiff
path: root/manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'manager.c')
-rw-r--r--manager.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/manager.c b/manager.c
index fca1963af1..3bbc85542c 100644
--- a/manager.c
+++ b/manager.c
@@ -16,6 +16,7 @@
#include "strv.h"
#include "log.h"
#include "util.h"
+#include "ratelimit.h"
static int manager_setup_signals(Manager *m) {
sigset_t mask;
@@ -57,6 +58,7 @@ Manager* manager_new(void) {
return NULL;
m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = -1;
+ m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
goto fail;
@@ -76,6 +78,10 @@ Manager* manager_new(void) {
if (manager_setup_signals(m) < 0)
goto fail;
+ /* FIXME: this should be called only when the D-Bus bus daemon is running */
+ if (bus_init(m) < 0)
+ goto fail;
+
return m;
fail:
@@ -100,6 +106,8 @@ void manager_free(Manager *m) {
if (unit_vtable[c]->shutdown)
unit_vtable[c]->shutdown(m);
+ bus_done(m);
+
hashmap_free(m->units);
hashmap_free(m->jobs);
hashmap_free(m->transaction_jobs);
@@ -1137,7 +1145,7 @@ static int process_event(Manager *m, struct epoll_event *ev, bool *quit) {
case WATCH_FD:
/* Some fd event, to be dispatched to the units */
- UNIT_VTABLE(w->unit)->fd_event(w->unit, w->fd, ev->events, w);
+ UNIT_VTABLE(w->data.unit)->fd_event(w->data.unit, w->fd, ev->events, w);
break;
case WATCH_TIMER: {
@@ -1153,7 +1161,7 @@ static int process_event(Manager *m, struct epoll_event *ev, bool *quit) {
return k < 0 ? -errno : -EIO;
}
- UNIT_VTABLE(w->unit)->timer_event(w->unit, v, w);
+ UNIT_VTABLE(w->data.unit)->timer_event(w->data.unit, v, w);
break;
}
@@ -1167,6 +1175,14 @@ static int process_event(Manager *m, struct epoll_event *ev, bool *quit) {
device_fd_event(m, ev->events);
break;
+ case WATCH_DBUS_WATCH:
+ bus_watch_event(m, w, ev->events);
+ break;
+
+ case WATCH_DBUS_TIMEOUT:
+ bus_timeout_event(m, w, ev->events);
+ break;
+
default:
assert_not_reached("Unknown epoll event type.");
}
@@ -1178,14 +1194,27 @@ int manager_loop(Manager *m) {
int r;
bool quit = false;
+ RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 1000);
+
assert(m);
for (;;) {
struct epoll_event event;
int n;
+ if (!ratelimit_test(&rl)) {
+ /* Yay, something is going seriously wrong, pause a little */
+ log_warning("Looping too fast. Throttling execution a little.");
+ sleep(1);
+ }
+
manager_dispatch_run_queue(m);
+ if (m->request_bus_dispatch) {
+ bus_dispatch(m);
+ continue;
+ }
+
if ((n = epoll_wait(m->epoll_fd, &event, 1, -1)) < 0) {
if (errno == -EINTR)
@@ -1203,3 +1232,28 @@ int manager_loop(Manager *m) {
return 0;
}
}
+
+int manager_get_unit_from_dbus_path(Manager *m, const char *s, Unit **_u) {
+ char *n;
+ Unit *u;
+
+ assert(m);
+ assert(s);
+ assert(_u);
+
+ if (!startswith(s, "/org/freedesktop/systemd1/unit/"))
+ return -EINVAL;
+
+ if (!(n = bus_path_unescape(s+31)))
+ return -ENOMEM;
+
+ u = manager_get_unit(m, n);
+ free(n);
+
+ if (!u)
+ return -ENOENT;
+
+ *_u = u;
+
+ return 0;
+}