[libvirt] [PATCH] Make virInitialize be called in multithreading environment

Guannan Ren gren at redhat.com
Wed Feb 15 13:16:02 UTC 2012


     When initializing libvirt shared library, calling virOnce
     to make load hypervisor drivers and create thread local key
     only once.

---
 src/libvirt.c              |  131 +++++++++++++++++++------------------------
 src/util/threads-pthread.c |    8 ++-
 2 files changed, 64 insertions(+), 75 deletions(-)

diff --git a/src/libvirt.c b/src/libvirt.c
index a55d823..4656779 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -106,7 +106,8 @@ static int virNWFilterDriverTabCount = 0;
 static virStateDriverPtr virStateDriverTab[MAX_DRIVERS];
 static int virStateDriverTabCount = 0;
 #endif
-static int initialized = 0;
+static int virInitResult = 0;
+static virOnceControl virOnceKey = VIR_ONCE_CONTROL_INITIALIZER;
 
 #if defined(POLKIT_AUTH)
 static int virConnectAuthGainPolkit(const char *privilege) {
@@ -379,30 +380,19 @@ static struct gcry_thread_cbs virTLSThreadImpl = {
     } while (0)
 
 /**
- * virInitialize:
- *
- * Initialize the library. It's better to call this routine at startup
- * in multithreaded applications to avoid potential race when initializing
- * the library.
- *
- * Calling virInitialize is mandatory, unless your first API call is one of
- * virConnectOpen*.
- *
- * Returns 0 in case of success, -1 in case of error
+ * Initialize global variable and load supported
+ * hypervisor drivers once.
  */
-int
-virInitialize(void)
+static void
+virInitializeOnce(void)
 {
-    if (initialized)
-        return 0;
-
-    initialized = 1;
+    if (virInitResult < 0)
+        return;
 
-    if (virThreadInitialize() < 0 ||
-        virErrorInitialize() < 0 ||
+    if (virErrorInitialize() < 0 ||
         virRandomInitialize(time(NULL) ^ getpid()) ||
         virNodeSuspendInit() < 0)
-        return -1;
+        goto failed;
 
     gcry_control(GCRYCTL_SET_THREAD_CBS, &virTLSThreadImpl);
     gcry_check_version(NULL);
@@ -414,12 +404,9 @@ virInitialize(void)
     VIR_DEBUG("register drivers");
 
 #if HAVE_WINSOCK2_H
-    if (winsock_init () == -1) return -1;
+    if (winsock_init () == -1) goto failed;
 #endif
 
-    if (!bindtextdomain(PACKAGE, LOCALEDIR))
-        return -1;
-
     /*
      * Note that the order is important: the first ones have a higher
      * priority when calling virConnectOpen.
@@ -459,36 +446,65 @@ virInitialize(void)
 # endif
 #else
 # ifdef WITH_TEST
-    if (testRegister() == -1) return -1;
+    if (testRegister() == -1) goto failed;
 # endif
 # ifdef WITH_XEN
-    if (xenRegister () == -1) return -1;
+    if (xenRegister () == -1) goto failed;
 # endif
 # ifdef WITH_OPENVZ
-    if (openvzRegister() == -1) return -1;
+    if (openvzRegister() == -1) goto failed;
 # endif
 # ifdef WITH_VMWARE
-    if (vmwareRegister() == -1) return -1;
+    if (vmwareRegister() == -1) goto failed;
 # endif
 # ifdef WITH_PHYP
-    if (phypRegister() == -1) return -1;
+    if (phypRegister() == -1) goto failed;
 # endif
 # ifdef WITH_VBOX
-    if (vboxRegister() == -1) return -1;
+    if (vboxRegister() == -1) goto failed;
 # endif
 # ifdef WITH_ESX
-    if (esxRegister() == -1) return -1;
+    if (esxRegister() == -1) goto failed;
 # endif
 # ifdef WITH_HYPERV
-    if (hypervRegister() == -1) return -1;
+    if (hypervRegister() == -1) goto failed;
 # endif
 # ifdef WITH_XENAPI
-    if (xenapiRegister() == -1) return -1;
+    if (xenapiRegister() == -1) goto failed;
 # endif
 # ifdef WITH_REMOTE
-    if (remoteRegister () == -1) return -1;
+    if (remoteRegister () == -1) goto failed;
 # endif
 #endif
+    return;
+
+failed:
+    virInitResult = -1;
+}
+
+/**
+ * virInitialize:
+ *
+ * Initialize the library. It could be either called directly
+ * or be called via one of virConnectOpen* in multithreaded
+ * applications.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+virInitialize(void)
+{
+    int ret;
+
+    if (virThreadInitialize() < 0)
+        return -1;
+
+    if (!bindtextdomain(PACKAGE, LOCALEDIR))
+        return -1;
+
+    ret = virOnce(&virOnceKey, virInitializeOnce);
+    if (ret < 0 || virInitResult < 0)
+        return -1;
 
     return 0;
 }
@@ -573,9 +589,6 @@ DllMain (HINSTANCE instance ATTRIBUTE_UNUSED,
 int
 virRegisterNetworkDriver(virNetworkDriverPtr driver)
 {
-    if (virInitialize() < 0)
-      return -1;
-
     if (driver == NULL) {
         virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
         return -1;
@@ -606,9 +619,6 @@ virRegisterNetworkDriver(virNetworkDriverPtr driver)
 int
 virRegisterInterfaceDriver(virInterfaceDriverPtr driver)
 {
-    if (virInitialize() < 0)
-      return -1;
-
     if (driver == NULL) {
         virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
         return -1;
@@ -639,9 +649,6 @@ virRegisterInterfaceDriver(virInterfaceDriverPtr driver)
 int
 virRegisterStorageDriver(virStorageDriverPtr driver)
 {
-    if (virInitialize() < 0)
-      return -1;
-
     if (driver == NULL) {
         virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
         return -1;
@@ -672,9 +679,6 @@ virRegisterStorageDriver(virStorageDriverPtr driver)
 int
 virRegisterDeviceMonitor(virDeviceMonitorPtr driver)
 {
-    if (virInitialize() < 0)
-      return -1;
-
     if (driver == NULL) {
         virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
         return -1;
@@ -705,9 +709,6 @@ virRegisterDeviceMonitor(virDeviceMonitorPtr driver)
 int
 virRegisterSecretDriver(virSecretDriverPtr driver)
 {
-    if (virInitialize() < 0)
-      return -1;
-
     if (driver == NULL) {
         virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
         return -1;
@@ -738,9 +739,6 @@ virRegisterSecretDriver(virSecretDriverPtr driver)
 int
 virRegisterNWFilterDriver(virNWFilterDriverPtr driver)
 {
-    if (virInitialize() < 0)
-      return -1;
-
     if (driver == NULL) {
         virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
         return -1;
@@ -774,9 +772,6 @@ virRegisterDriver(virDriverPtr driver)
 {
     VIR_DEBUG("driver=%p name=%s", driver, driver ? NULLSTR(driver->name) : "(null)");
 
-    if (virInitialize() < 0)
-        return -1;
-
     if (driver == NULL) {
         virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
         return -1;
@@ -814,9 +809,6 @@ virRegisterDriver(virDriverPtr driver)
 int
 virRegisterStateDriver(virStateDriverPtr driver)
 {
-    if (virInitialize() < 0)
-      return -1;
-
     if (driver == NULL) {
         virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
         return -1;
@@ -844,9 +836,6 @@ virRegisterStateDriver(virStateDriverPtr driver)
 int virStateInitialize(int privileged) {
     int i, ret = 0;
 
-    if (virInitialize() < 0)
-        return -1;
-
     for (i = 0 ; i < virStateDriverTabCount ; i++) {
         if (virStateDriverTab[i]->initialize &&
             virStateDriverTab[i]->initialize(privileged) < 0) {
@@ -942,9 +931,8 @@ virGetVersion(unsigned long *libVer, const char *type ATTRIBUTE_UNUSED,
 {
     VIR_DEBUG("libVir=%p, type=%s, typeVer=%p", libVer, type, typeVer);
 
-    if (!initialized)
-        if (virInitialize() < 0)
-            goto error;
+    if (virInitialize() < 0)
+        goto error;
 
     if (libVer == NULL)
         goto error;
@@ -1342,9 +1330,8 @@ virConnectPtr
 virConnectOpen (const char *name)
 {
     virConnectPtr ret = NULL;
-    if (!initialized)
-        if (virInitialize() < 0)
-            goto error;
+    if (virInitialize() < 0)
+        goto error;
 
     VIR_DEBUG("name=%s", name);
     ret = do_open (name, NULL, 0);
@@ -1376,9 +1363,8 @@ virConnectPtr
 virConnectOpenReadOnly(const char *name)
 {
     virConnectPtr ret = NULL;
-    if (!initialized)
-        if (virInitialize() < 0)
-            goto error;
+    if (virInitialize() < 0)
+        goto error;
 
     VIR_DEBUG("name=%s", name);
     ret = do_open (name, NULL, VIR_CONNECT_RO);
@@ -1414,9 +1400,8 @@ virConnectOpenAuth(const char *name,
                    unsigned int flags)
 {
     virConnectPtr ret = NULL;
-    if (!initialized)
-        if (virInitialize() < 0)
-            goto error;
+    if (virInitialize() < 0)
+        goto error;
 
     VIR_DEBUG("name=%s, auth=%p, flags=%x", NULLSTR(name), auth, flags);
     ret = do_open (name, auth, flags);
diff --git a/src/util/threads-pthread.c b/src/util/threads-pthread.c
index ea64887..15d1407 100644
--- a/src/util/threads-pthread.c
+++ b/src/util/threads-pthread.c
@@ -42,10 +42,14 @@ void virThreadOnExit(void)
 
 int virOnce(virOnceControlPtr once, virOnceFunc init)
 {
-    return pthread_once(&once->once, init);
+    int ret;
+    if ((ret = pthread_once(&once->once, init)) != 0) {
+        errno = ret;
+        return -1;
+    }
+    return 0;
 }
 
-
 int virMutexInit(virMutexPtr m)
 {
     int ret;
-- 
1.7.7.5




More information about the libvir-list mailing list