mirror of https://gitee.com/openkylin/libvirt.git
84 lines
5.3 KiB
HTML
84 lines
5.3 KiB
HTML
|
<?xml version="1.0"?>
|
||
|
<html>
|
||
|
<body>
|
||
|
<h1 >Handling of errors</h1>
|
||
|
<p>The main goals of libvirt when it comes to error handling are:</p>
|
||
|
<ul>
|
||
|
<li>provide as much detail as possible</li>
|
||
|
<li>provide the information as soon as possible</li>
|
||
|
<li>dont force the library user into one style of error handling</li>
|
||
|
</ul>
|
||
|
<p>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.</p>
|
||
|
<p>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</p>
|
||
|
<p>So error handling in the code is the following:</p>
|
||
|
<ol>
|
||
|
<li>if the error can be associated to a connection for example when failing
|
||
|
to look up a domain
|
||
|
<ol><li>if there is a callback associated to the connection set with <a href="html/libvirt-virterror.html#virConnSetErrorFunc">virConnSetErrorFunc</a>,
|
||
|
call it with the error information</li><li>otherwise if there is a global callback set with <a href="html/libvirt-virterror.html#virSetErrorFunc">virSetErrorFunc</a>,
|
||
|
call it with the error information</li><li>otherwise call <a href="html/libvirt-virterror.html#virDefaultErrorFunc">virDefaultErrorFunc</a>
|
||
|
which is the default error function of the library issuing the error
|
||
|
on stderr</li><li>save the error in the connection for later retrieval with <a href="html/libvirt-virterror.html#virConnGetLastError">virConnGetLastError</a></li></ol></li>
|
||
|
<li>otherwise like when failing to create an hypervisor connection:
|
||
|
<ol><li>if there is a global callback set with <a href="html/libvirt-virterror.html#virSetErrorFunc">virSetErrorFunc</a>,
|
||
|
call it with the error information</li><li>otherwise call <a href="html/libvirt-virterror.html#virDefaultErrorFunc">virDefaultErrorFunc</a>
|
||
|
which is the default error function of the library issuing the error
|
||
|
on stderr</li><li>save the error in the connection for later retrieval with <a href="html/libvirt-virterror.html#virGetLastError">virGetLastError</a></li></ol></li>
|
||
|
</ol>
|
||
|
<p>In all cases the error information is provided as a <a href="html/libvirt-virterror.html#virErrorPtr">virErrorPtr</a> pointer to
|
||
|
read-only structure <a href="html/libvirt-virterror.html#virError">virError</a> containing the
|
||
|
following fields:</p>
|
||
|
<ul>
|
||
|
<li>code: an error number from the <a href="html/libvirt-virterror.html#virErrorNumber">virErrorNumber</a>
|
||
|
enum</li>
|
||
|
<li>domain: an enum indicating which part of libvirt raised the error see
|
||
|
<a href="html/libvirt-virterror.html#virErrorDomain">virErrorDomain</a></li>
|
||
|
<li>level: the error level, usually VIR_ERR_ERROR, though there is room for
|
||
|
warnings like VIR_ERR_WARNING</li>
|
||
|
<li>message: the full human-readable formatted string of the error</li>
|
||
|
<li>conn: if available a pointer to the <a href="html/libvirt-libvirt.html#virConnectPtr">virConnectPtr</a>
|
||
|
connection to the hypervisor where this happened</li>
|
||
|
<li>dom: if available a pointer to the <a href="html/libvirt-libvirt.html#virDomainPtr">virDomainPtr</a> domain
|
||
|
targeted in the operation</li>
|
||
|
</ul>
|
||
|
<p>and then extra raw information about the error which may be initialized
|
||
|
to 0 or NULL if unused</p>
|
||
|
<ul>
|
||
|
<li>str1, str2, str3: string information, usually str1 is the error
|
||
|
message format</li>
|
||
|
<li>int1, int2: integer information</li>
|
||
|
</ul>
|
||
|
<p>So usually, setting up specific error handling with libvirt consist of
|
||
|
registering an handler with with <a href="html/libvirt-virterror.html#virSetErrorFunc">virSetErrorFunc</a> or
|
||
|
with <a href="html/libvirt-virterror.html#virConnSetErrorFunc">virConnSetErrorFunc</a>,
|
||
|
check the value of the code value, take appropriate action, if needed let
|
||
|
libvirt print the error on stderr by calling <a href="html/libvirt-virterror.html#virDefaultErrorFunc">virDefaultErrorFunc</a>.
|
||
|
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 <a href="html/libvirt-virterror.html#virResetLastError">virResetError</a> or <a href="html/libvirt-virterror.html#virConnResetLastError">virConnResetLastError</a>
|
||
|
once an error has been processed fully.</p>
|
||
|
<p>At the python level, there only a global reporting callback function at
|
||
|
this point, see the error.py example about it:</p>
|
||
|
<pre>def handler(ctxt, err):
|
||
|
global errno
|
||
|
|
||
|
#print "handler(%s, %s)" % (ctxt, err)
|
||
|
errno = err
|
||
|
|
||
|
libvirt.registerErrorHandler(handler, 'context') </pre>
|
||
|
<p>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.</p>
|
||
|
</body>
|
||
|
</html>
|