chiark / gitweb /
core: correctly unregister PIDs from PID hashtables
[elogind.git] / src / core / unit.c
index 1bbcb39d3227209ee1a537795112248ac947f458..85250ca2aa74a2dac7f0abc5026380d7cea903ba 100644 (file)
@@ -328,7 +328,8 @@ void unit_add_to_dbus_queue(Unit *u) {
                 return;
 
         /* Shortcut things if nobody cares */
-        if (set_isempty(u->manager->subscribed)) {
+        if (sd_bus_track_count(u->manager->subscribed) <= 0 &&
+            set_isempty(u->manager->private_buses)) {
                 u->sent_dbus_new_signal = true;
                 return;
         }
@@ -1703,11 +1704,11 @@ int unit_watch_pid(Unit *u, pid_t pid) {
         /* Watch a specific PID. We only support one or two units
          * watching each PID for now, not more. */
 
-        r = hashmap_ensure_allocated(&u->manager->watch_pids1, trivial_hash_func, trivial_compare_func);
+        r = set_ensure_allocated(&u->pids, trivial_hash_func, trivial_compare_func);
         if (r < 0)
                 return r;
 
-        r = set_ensure_allocated(&u->pids, trivial_hash_func, trivial_compare_func);
+        r = hashmap_ensure_allocated(&u->manager->watch_pids1, trivial_hash_func, trivial_compare_func);
         if (r < 0)
                 return r;
 
@@ -1736,7 +1737,17 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
         set_remove(u->pids, LONG_TO_PTR(pid));
 }
 
-static int watch_pids_in_path(Unit *u, const char *path) {
+void unit_unwatch_all_pids(Unit *u) {
+        assert(u);
+
+        while (!set_isempty(u->pids))
+                unit_unwatch_pid(u, PTR_TO_LONG(set_first(u->pids)));
+
+        set_free(u->pids);
+        u->pids = NULL;
+}
+
+static int unit_watch_pids_in_path(Unit *u, const char *path) {
         _cleanup_closedir_ DIR *d = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int ret = 0, r;
@@ -1774,7 +1785,7 @@ static int watch_pids_in_path(Unit *u, const char *path) {
                         if (!p)
                                 return -ENOMEM;
 
-                        r = watch_pids_in_path(u, p);
+                        r = unit_watch_pids_in_path(u, p);
                         if (r < 0 && ret >= 0)
                                 ret = r;
                 }
@@ -1787,31 +1798,15 @@ static int watch_pids_in_path(Unit *u, const char *path) {
         return ret;
 }
 
-
 int unit_watch_all_pids(Unit *u) {
         assert(u);
 
-        if (!u->cgroup_path)
-                return -ENOENT;
-
         /* Adds all PIDs from our cgroup to the set of PIDs we watch */
 
-        return watch_pids_in_path(u, u->cgroup_path);
-}
-
-void unit_unwatch_all_pids(Unit *u) {
-        Iterator i;
-        void *e;
-
-        assert(u);
-
-        SET_FOREACH(e, u->pids, i) {
-                hashmap_remove_value(u->manager->watch_pids1, e, u);
-                hashmap_remove_value(u->manager->watch_pids2, e, u);
-        }
+        if (!u->cgroup_path)
+                return -ENOENT;
 
-        set_free(u->pids);
-        u->pids = NULL;
+        return unit_watch_pids_in_path(u, u->cgroup_path);
 }
 
 void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) {
@@ -1829,7 +1824,7 @@ void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) {
                         continue;
 
                 if (!pid_is_unwaited(pid))
-                        set_remove(u->pids, e);
+                        unit_unwatch_pid(u, pid);
         }
 }
 
@@ -2777,15 +2772,32 @@ void unit_ref_unset(UnitRef *ref) {
         ref->unit = NULL;
 }
 
-int unit_exec_context_defaults(Unit *u, ExecContext *c) {
+int unit_cgroup_context_init_defaults(Unit *u, CGroupContext *c) {
+        assert(u);
+        assert(c);
+
+        /* Copy in the manager defaults into the cgroup context,
+         * _before_ the rest of the settings have been initialized */
+
+        c->cpu_accounting = u->manager->default_cpu_accounting;
+        c->blockio_accounting = u->manager->default_blockio_accounting;
+        c->memory_accounting = u->manager->default_memory_accounting;
+
+        return 0;
+}
+
+int unit_exec_context_patch_defaults(Unit *u, ExecContext *c) {
         unsigned i;
         int r;
 
         assert(u);
         assert(c);
 
+        /* Patch in the manager defaults into the exec context,
+         * _after_ the rest of the settings have been initialized */
+
         /* This only copies in the ones that need memory */
-        for (i = 0; i < RLIMIT_NLIMITS; i++)
+        for (i = 0; i < _RLIMIT_MAX; i++)
                 if (u->manager->rlimit[i] && !c->rlimit[i]) {
                         c->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1);
                         if (!c->rlimit[i])
@@ -2800,6 +2812,14 @@ int unit_exec_context_defaults(Unit *u, ExecContext *c) {
                         return r;
         }
 
+        if (u->manager->running_as == SYSTEMD_USER &&
+            (c->syscall_whitelist ||
+             !set_isempty(c->syscall_filter) ||
+             !set_isempty(c->syscall_archs) ||
+             c->address_families_whitelist ||
+             !set_isempty(c->address_families)))
+                c->no_new_privileges = true;
+
         return 0;
 }
 
@@ -3155,11 +3175,9 @@ int unit_require_mounts_for(Unit *u, const char *path) {
                 return 0;
         }
 
-        r = strv_push(&u->requires_mounts_for, p);
-        if (r < 0) {
-                free(p);
+        r = strv_consume(&u->requires_mounts_for, p);
+        if (r < 0)
                 return r;
-        }
 
         PATH_FOREACH_PREFIX_MORE(prefix, p) {
                 Set *x;