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