]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: fix killing of scopes 7096/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 14 Oct 2017 15:09:54 +0000 (17:09 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 19 Oct 2017 06:49:01 +0000 (08:49 +0200)
scope_abandon() called unit_watch_all_pids() to check if there are any pids in
the cgroup, but unit_watch_all_pids() does nothing (and returns an empty set of
pids) when cg_unified_controller(SYSTEMD) returns true. On hybrid or unified,
cg_unified_controller(SYSTEMD) returns 1, so scope_abandon() thinks the scope
is empty, even though it's not, and marks the scope dead prematurely.

Example output after the scope is marked dead with processes still being present:

● session-24.scope - Session 24 of user guest
   Loaded: loaded (/run/systemd/transient/session-24.scope; transient; vendor preset: disabled)
Transient: yes
   Active: inactive (dead) since Sat 2017-10-14 15:36:22 CEST; 5min ago
    Tasks: 1
   CGroup: /user.slice/user-1001.slice/session-24.scope
           └─17309 sleep infinity

Subsequent calls to stop the scope unit do nothing, because systemd thinks the
scope is already dead.

https://bugzilla.redhat.com/show_bug.cgi?id=1486859

This is easily reproducible on both F26 and F27:

> ssh guest@localhost
$ pulseaudio & sleep infinity & disown; exit
$ systemctl status $$
> systemctl status session-NN.scope

Tested with unified, hybrid, and legacy layouts, seems to work.

src/core/scope.c

index 4cd5e3dd2a6cb1fdae9d58dcd2dc6d8962de8f55..7e789ed14789e61a799559e884355049762eac3a 100644 (file)
@@ -522,6 +522,7 @@ int scope_abandon(Scope *s) {
 
         s->was_abandoned = true;
         s->controller = mfree(s->controller);
+        scope_set_state(s, SCOPE_ABANDONED);
 
         /* The client is no longer watching the remaining processes,
          * so let's step in here, under the assumption that the
@@ -531,12 +532,6 @@ int scope_abandon(Scope *s) {
         unit_tidy_watch_pids(UNIT(s), 0, 0);
         unit_watch_all_pids(UNIT(s));
 
-        /* If the PID set is empty now, then let's finish this off */
-        if (set_isempty(UNIT(s)->pids))
-                scope_notify_cgroup_empty_event(UNIT(s));
-        else
-                scope_set_state(s, SCOPE_ABANDONED);
-
         return 0;
 }