Comment 14 for bug 1397130

Revision history for this message
Don Bowman (donbowman) wrote :

so part of the issue is cgm_* is not thread safe, but is called from various threads.
e.g. if u start libvirtd w/ several instances already running, it will call cgm_dbus_connect from each.

there is a pair of global variable:
static NihDBusProxy *cgroup_manager = NULL;
bool cgm_running = false;

in src/util/cgmanager.c, and they cause this issue.

cgm_dbus_connect() overwrites cgroup_manager regardless of the state of cgm_running (and cgm_running is set @ the end of it anyway).

The use of pthread_once is probably part of the solution. The below patch partially corrects.

--- libvirt-1.2.8.orig/src/util/cgmanager.c
+++ libvirt-1.2.8/src/util/cgmanager.c
@@ -40,10 +40,12 @@
 static NihDBusProxy *cgroup_manager = NULL;
 bool cgm_running = false;

+static pthread_once_t cgmanager_is_init = PTHREAD_ONCE_INIT;
+
 VIR_LOG_INIT("util.cgmanager");

 #define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock"
-bool cgm_dbus_connect(void)
+static bool _cgm_dbus_connect(void)
 {
     DBusError dbus_error;
     DBusConnection *connection;
@@ -83,6 +85,11 @@ bool cgm_dbus_connect(void)
     return true;
 }

+bool cgm_dbus_connect(void)
+{
+ pthread_once(&cgmanager_is_init, _cgm_dbus_connect);
+}
+
 void cgm_dbus_disconnect(void)
 {
     if (cgroup_manager) {
--- libvirt-1.2.8.orig/src/util/cgmanager.h
+++ libvirt-1.2.8/src/util/cgmanager.h
@@ -30,6 +30,7 @@
 #include <nih/alloc.h>
 #include <nih/error.h>
 #include <nih/string.h>
+#include <pthread.h>

 extern bool cgm_running;

Its not clear to me the underlying libs are all thread safe (e.g. https://bugs.launchpad.net/ubuntu/+source/libnih/+bug/1294200)

there would remain the problem of... what if cgmanager goes away. 1 thread will find it, does it reconnect and fix the others?