Pablo Greco 48fc63
From 019b19130bcba9d88c0328b40f2639e6ebbb513c Mon Sep 17 00:00:00 2001
Pablo Greco 48fc63
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Pablo Greco 48fc63
Date: Tue, 13 Feb 2018 23:57:43 +0100
Pablo Greco 48fc63
Subject: [PATCH] pid1: properly remove references to the unit from gc queue
Pablo Greco 48fc63
 during final cleanup
Pablo Greco 48fc63
Pablo Greco 48fc63
When various references to the unit were dropped during cleanup in unit_free(),
Pablo Greco 48fc63
add_to_gc_queue() could be called on this unit. If the unit was previously in
Pablo Greco 48fc63
the gc queue (at the time when unit_free() was called on it), this wouldn't
Pablo Greco 48fc63
matter, because it'd have in_gc_queue still set even though it was already
Pablo Greco 48fc63
removed from the queue. But if it wasn't set, then the unit could be added to
Pablo Greco 48fc63
the queue. Then after unit_free() would deallocate the unit, we would be left
Pablo Greco 48fc63
with a dangling pointer in gc_queue.
Pablo Greco 48fc63
Pablo Greco 48fc63
A unit could be added to the gc queue in two places called from unit_free():
Pablo Greco 48fc63
in the job_install calls, and in unit_ref_unset(). The first was OK, because
Pablo Greco 48fc63
it was above the LIST_REMOVE(gc_queue,...) call, but the second was not, because
Pablo Greco 48fc63
it was after that. Move the all LIST_REMOVE() calls down.
Pablo Greco 48fc63
Pablo Greco 48fc63
(cherry picked from commit 1bdf2790025e661e41894129eb390bb032b88585)
Pablo Greco 48fc63
(cherry picked from commit 8f1df942e2237124f7559176081af7ac631d3422)
Pablo Greco 48fc63
Pablo Greco 48fc63
Related: #1729228
Pablo Greco 48fc63
---
Pablo Greco 48fc63
 src/core/unit.c | 34 +++++++++++++++++-----------------
Pablo Greco 48fc63
 1 file changed, 17 insertions(+), 17 deletions(-)
Pablo Greco 48fc63
Pablo Greco 48fc63
diff --git a/src/core/unit.c b/src/core/unit.c
Pablo Greco 48fc63
index 63f00acc0a..def36a0930 100644
Pablo Greco 48fc63
--- a/src/core/unit.c
Pablo Greco 48fc63
+++ b/src/core/unit.c
Pablo Greco 48fc63
@@ -506,23 +506,6 @@ void unit_free(Unit *u) {
Pablo Greco 48fc63
         for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
Pablo Greco 48fc63
                 bidi_set_free(u, u->dependencies[d]);
Pablo Greco 48fc63
 
Pablo Greco 48fc63
-        if (u->type != _UNIT_TYPE_INVALID)
Pablo Greco 48fc63
-                LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u);
Pablo Greco 48fc63
-
Pablo Greco 48fc63
-        if (u->in_load_queue)
Pablo Greco 48fc63
-                LIST_REMOVE(load_queue, u->manager->load_queue, u);
Pablo Greco 48fc63
-
Pablo Greco 48fc63
-        if (u->in_dbus_queue)
Pablo Greco 48fc63
-                LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
Pablo Greco 48fc63
-
Pablo Greco 48fc63
-        if (u->in_cleanup_queue)
Pablo Greco 48fc63
-                LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u);
Pablo Greco 48fc63
-
Pablo Greco 48fc63
-        if (u->in_gc_queue) {
Pablo Greco 48fc63
-                LIST_REMOVE(gc_queue, u->manager->gc_queue, u);
Pablo Greco 48fc63
-                u->manager->n_in_gc_queue--;
Pablo Greco 48fc63
-        }
Pablo Greco 48fc63
-
Pablo Greco 48fc63
         if (u->in_target_deps_queue)
Pablo Greco 48fc63
                 LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u);
Pablo Greco 48fc63
 
Pablo Greco 48fc63
@@ -543,6 +526,23 @@ void unit_free(Unit *u) {
Pablo Greco 48fc63
         while (u->refs_by_target)
Pablo Greco 48fc63
                 unit_ref_unset(u->refs_by_target);
Pablo Greco 48fc63
 
Pablo Greco 48fc63
+        if (u->type != _UNIT_TYPE_INVALID)
Pablo Greco 48fc63
+                LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u);
Pablo Greco 48fc63
+
Pablo Greco 48fc63
+        if (u->in_load_queue)
Pablo Greco 48fc63
+                LIST_REMOVE(load_queue, u->manager->load_queue, u);
Pablo Greco 48fc63
+
Pablo Greco 48fc63
+        if (u->in_dbus_queue)
Pablo Greco 48fc63
+                LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
Pablo Greco 48fc63
+
Pablo Greco 48fc63
+        if (u->in_cleanup_queue)
Pablo Greco 48fc63
+                LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u);
Pablo Greco 48fc63
+
Pablo Greco 48fc63
+        if (u->in_gc_queue) {
Pablo Greco 48fc63
+                LIST_REMOVE(gc_queue, u->manager->gc_queue, u);
Pablo Greco 48fc63
+                u->manager->n_in_gc_queue--;
Pablo Greco 48fc63
+        }
Pablo Greco 48fc63
+
Pablo Greco 48fc63
         condition_free_list(u->conditions);
Pablo Greco 48fc63
         condition_free_list(u->asserts);
Pablo Greco 48fc63