Blob Blame History Raw
From 1ed560ffff6753d79f2f1da81447e5f8d3628ec1 Mon Sep 17 00:00:00 2001
From: Alexander Solganik <solganik@gmail.com>
Date: Wed, 29 Apr 2015 10:06:40 +0300
Subject: [PATCH] machined: force machined to dispatch messages

Fixes  https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=1172387.

Machined works in the follwing way :

loop :
       1) perform GC (Note at the end)
       2) read messages from DBUS and dispatch one
       3) if more messages pending goto (1)
       3) perform GC (NOTE at the end)
       4) poll on DBUS fd
       5) goto step 1

This works fine, except that in step (3) and (1)
there is a message send/reply receive of
 r = bus_method_call_with_reply(
                        manager->bus,
                        "org.freedesktop.systemd1",
                        "/org/freedesktop/systemd1",
                        "org.freedesktop.systemd1.Manager",
                        "StopUnit",
                        &reply,
                        error,
                        DBUS_TYPE_STRING, &unit,
                        DBUS_TYPE_STRING, &fail,
                        DBUS_TYPE_INVALID);

which causes network layer to read/write messages to DBUS fd. In case that any
other message gets in during this send/receive cycle it wont be processed till
next stage (2) which will occur only in case that more messages are received
by machined.

Cherry-picked from: rhel-only
Resolves: #1243401
---
 src/machine/machined.c | 8 ++++++--
 src/machine/machined.h | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/machine/machined.c b/src/machine/machined.c
index ad804a1..531e7ad 100644
--- a/src/machine/machined.c
+++ b/src/machine/machined.c
@@ -243,20 +243,23 @@ fail:
         return r;
 }
 
-void manager_gc(Manager *m, bool drop_not_started) {
+bool manager_gc(Manager *m, bool drop_not_started) {
         Machine *machine;
+        bool dbus_send_receive_performed = false;
 
         assert(m);
 
         while ((machine = m->machine_gc_queue)) {
                 LIST_REMOVE(Machine, gc_queue, m->machine_gc_queue, machine);
                 machine->in_gc_queue = false;
+                dbus_send_receive_performed = true;
 
                 if (machine_check_gc(machine, drop_not_started) == 0) {
                         machine_stop(machine);
                         machine_free(machine);
                 }
         }
+        return dbus_send_receive_performed;
 }
 
 int manager_startup(Manager *m) {
@@ -301,7 +304,8 @@ int manager_run(Manager *m) {
                 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
                         continue;
 
-                manager_gc(m, true);
+                if (manager_gc(m, true))
+                       continue;
 
                 n = epoll_wait(m->epoll_fd, &event, 1, -1);
                 if (n < 0) {
diff --git a/src/machine/machined.h b/src/machine/machined.h
index 780f516..3245e05 100644
--- a/src/machine/machined.h
+++ b/src/machine/machined.h
@@ -59,7 +59,7 @@ int manager_enumerate_machines(Manager *m);
 int manager_startup(Manager *m);
 int manager_run(Manager *m);
 
-void manager_gc(Manager *m, bool drop_not_started);
+bool manager_gc(Manager *m, bool drop_not_started);
 
 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine);