https://bugzilla.redhat.com/show_bug.cgi?id=895882 virDomainSnapshotGetDomain returns snapshot->domain without incrementing domain's reference counter. The autogenerated python wrapper around this API did not honor this fact and created a new virDomain object from the snapshot's domain. When this object is deleted, it calls virDomainFree. This caused python client to crash when the domain object is accessed after it has been freed. --- python/generator.py | 1 + python/libvirt-override.c | 24 ++++++++++++++++++++++++ src/libvirt.c | 6 +++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/python/generator.py b/python/generator.py index f853d77..7e76c2a 100755 --- a/python/generator.py +++ b/python/generator.py @@ -379,6 +379,7 @@ skip_impl = ( 'virConnectListDefinedInterfaces', 'virConnectListNWFilters', 'virDomainSnapshotListNames', + 'virDomainSnapshotGetDomain', 'virDomainSnapshotListChildrenNames', 'virConnGetLastError', 'virGetLastError', diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 8154024..92dc939 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -2212,6 +2212,29 @@ cleanup: } static PyObject * +libvirt_virDomainSnapshotGetDomain(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) +{ + virDomainPtr dom; + virDomainSnapshotPtr snapshot; + PyObject *pyobj_snapshot; + + if (!PyArg_ParseTuple(args, (char *)"O:virDomainSnapshotGetDomain", + &pyobj_snapshot)) + return NULL; + snapshot = PyvirDomainSnapshot_Get(pyobj_snapshot); + + LIBVIRT_BEGIN_ALLOW_THREADS; + dom = virDomainSnapshotGetDomain(snapshot); + LIBVIRT_END_ALLOW_THREADS; + + if (dom) + virDomainRef(dom); + + return libvirt_virDomainPtrWrap(dom); +} + +static PyObject * libvirt_virDomainListAllSnapshots(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { @@ -6674,6 +6697,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virConnectBaselineCPU", libvirt_virConnectBaselineCPU, METH_VARARGS, NULL}, {(char *) "virDomainGetJobInfo", libvirt_virDomainGetJobInfo, METH_VARARGS, NULL}, {(char *) "virDomainSnapshotListNames", libvirt_virDomainSnapshotListNames, METH_VARARGS, NULL}, + {(char *) "virDomainSnapshotGetDomain", libvirt_virDomainSnapshotGetDomain, METH_VARARGS, NULL}, {(char *) "virDomainListAllSnapshots", libvirt_virDomainListAllSnapshots, METH_VARARGS, NULL}, {(char *) "virDomainSnapshotListChildrenNames", libvirt_virDomainSnapshotListChildrenNames, METH_VARARGS, NULL}, {(char *) "virDomainSnapshotListAllChildren", libvirt_virDomainSnapshotListAllChildren, METH_VARARGS, NULL}, diff --git a/src/libvirt.c b/src/libvirt.c index d5d561c..5f36934 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -17850,7 +17850,11 @@ virDomainSnapshotGetName(virDomainSnapshotPtr snapshot) * virDomainSnapshotGetDomain: * @snapshot: a snapshot object * - * Get the domain that a snapshot was created for + * Get the domain that a snapshot was created for. The caller must not call + * virDomainFree() on the returned domain unless it calls virDomainRef() first + * as this function does not increment domain's reference counter. The returned + * object will be automatically freed with the end of life of the snapshot + * object. * * Returns the domain or NULL. */ -- 1.8.1.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list