On 02/28/2012 03:57 AM, Guido Winkelmann wrote:
>
> There's nothing in there between calling virDomainCreate() and
> virGetLastError(). There are no other threads, either.
>
> Anyway, I've fired up gdb now to see if I can find out where the error
> object gets lost.
I found out what is happening here:
I am using a C++ wrapper class for virDomainPtr, to make it fit better with
the RAII principles in that language. That means that, in the above code
snippet, even though it's not actually visible because it happens in the
constructor and destructor of a temporary object, the virDomainPtr for domain
gets copied once, virDomainRef() gets called on it, and after the attempt to
start the domain, virDomainFree() gets called.
The problem is that virDomainFree() will unconditionally call
virResetLastError().
Correct. _Every_ call to a libvirt API resets last error, _on entry_.
With that info, I could work around the problem, however, I still think that,
since virDomainFree() is a reference-counting free, it should only call
virResetLastError() when the reference count has actually reached 0. In fact,
it should probably even check whether the last error even belongs to the
domain being deleted.
Not possible - it is not known on entry whether this is the last
reference being freed. We've already fixed this sort of bug in libvirt
itself in the past, where the code in daemon/remote.c wasn't properly
passing errors back to the caller because the daemon glue code was
calling intermediate functions like virDomainFree(). Your wrapper
function that calls virDomainFree() on the temporary object needs to
save the error beforehand and restore it afterwords.
--
Eric Blake eblake(a)redhat.com +1-919-301-3266
Libvirt virtualization library
http://libvirt.org