Hi,
OK. Now I am using JNA to access libvirt. If we add another mutex which used to access
“initialized” parameter. This mutex must be pthread_mutex_init firstly and only once.
But it seems that there is no way to change libvirt code. I do it as following:
1. Changing libvirt JNA code in Connect.java
Old Code:
public Connect(String uri) throws LibvirtException {
VCP = libvirt.virConnectOpen(uri);
// Check for an error
processError();
ErrorHandler.processError(Libvirt.INSTANCE);
}
New Code:
public Connect(String uri) throws LibvirtException {
synchronized(this.getClass()) {
VCP = libvirt.virConnectOpen(uri);
}
// Check for an error
processError();
ErrorHandler.processError(Libvirt.INSTANCE);
}
This can make sure only that one thread can execute Connect. For a server application, we
only need one time. So the performance is OK
2. Changing libvirt code in libvirt.c
Old Code:
static int initialized = 0;
New Code:
static int volatile initialized = 0;
This can make sure the initialization will be executed once.
Would you give your comments for this solution?
B.R.
Benjamin Wang
From: Guannan Ren [mailto:gren@redhat.com]
Sent: 2012年9月29日 15:43
To: Benjamin Wang (gendwang)
Cc: Daniel Veillard; libvir-list(a)redhat.com; Yang Zhou (yangzho)
Subject: Re: [libvirt] Potential race condition problem
On 09/29/2012 03:07 PM, Benjamin Wang (gendwang) wrote:
Hi,
Currently virInitialize() method defined in libvirt.c has the following code:
int
virInitialize(void)
{
if (initialized)
return 0;
initialized = 1;
if (virThreadInitialize() < 0 ||
virErrorInitialize() < 0 ||
virRandomInitialize(time(NULL) ^ getpid()) ||
virNodeSuspendInit() < 0)
return -1;
……
}
When two threads access virInitialize method, there is no lock for the “initialized”
parameter. If the first thread enters this method and set “initialized” to 1,
the second thread could see that “initialized” is 1(Because initialized is not volatiled,
I say could). In some situation, before the first thread finishes all the
initialization,
the second thread could use some resources which should be initialized in Initialize
method.
If you have any comments, please let me know. Thanks!
B.R.
Benjamin Wang
As the comments above the function said,
"It's better to call this routine at startup in multithreaded applications
to avoid potential race when initializing the library."
Guannan