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