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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list