On Fri, Sep 03, 2010 at 01:02:09PM +0200, Matthias Bolte wrote:
Ah, okay, now I understand what you want to say.
You have two threads A and B. When A runs on its own then it's just
fine, but when you add B (that triggers an exception on purpose and
ignores it) then A picks it up and reports it. This is the point where
thread safety comes to mind.
libvirt stores errors in thread-local-storage. It uses
pthread_key_create/pthread_{get,set}specific for this (or
TlsAlloc/Tls{Get,Set}Value on Windows).
I think what's happening here is that all your threads in Java share
the same thread-local-storage. Therefore, thread A can pickup the
error triggered by thread B, that should not happen.
I'm not sure how to fix that.
Looking at the java code, I believe the problem is that the java
bindings are *not* using the threadsafe error APIs:
In Connect.java
/**
* call the error handling logic. Should be called after every libvirt call
*
* @throws LibvirtException
*/
protected void processError() throws LibvirtException {
ErrorHandler.processError(libvirt, VCP);
}
Which calls into
public static void processError(Libvirt libvirt, ConnectionPointer conn) throws
LibvirtException {
virError vError = new virError();
int errorCode = libvirt.virConnCopyLastError(conn, vError);
And virConnCopyLastError is *not* threadsafe:
/**
* virConnCopyLastError:
* @conn: pointer to the hypervisor connection
* @to: target to receive the copy
*
* Copy the content of the last error caught on that connection
*
* This method is not protected against access from multiple
* threads. In a multi-threaded application, always use the
* global virGetLastError() API which is backed by thread
* local storage.
Regards,
Daniel
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://deltacloud.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|