The main goals of libvirt when it comes to error handling are:
As result the library provide both synchronous, callback based and asynchronous error reporting. When an error happens in the library code the error is logged, allowing to retrieve it later and if the user registered an error callback it will be called synchronously. Once the call to libvirt ends the error can be detected by the return value and the full information for the last logged error can be retrieved.
To avoid as much as possible troubles with a global variable in a multithreaded environment, libvirt will associate when possible the errors to the current connection they are related to, that way the error is stored in a dynamic structure which can be made thread specific. Error callback can be set specifically to a connection with
So error handling in the code is the following:
In all cases the error information is provided as a virErrorPtr pointer to read-only structure virError containing the following fields:
and then extra raw information about the error which may be initialized to 0 or NULL if unused
So usually, setting up specific error handling with libvirt consist of registering a handler with virSetErrorFunc or with virConnSetErrorFunc, check the value of the code value, take appropriate action, if needed let libvirt print the error on stderr by calling virDefaultErrorFunc. For asynchronous error handing, set such a function doing nothing to avoid the error being reported on stderr, and call virConnGetLastError or virGetLastError when an API call returned an error value. It can be a good idea to use virResetError or virConnResetLastError once an error has been processed fully.
At the python level, there only a global reporting callback function at this point, see the error.py example about it:
def handler(ctxt, err): global errno #print "handler(%s, %s)" % (ctxt, err) errno = err libvirt.registerErrorHandler(handler, 'context')
the second argument to the registerErrorHandler function is passed as the first argument of the callback like in the C version. The error is a tuple containing the same field as a virError in C, but cast to Python.