[libvirt] [libvirt-python][PATCH] generator: Free strings after libvirt_charPtrWrap
Daniel P. Berrange
berrange at redhat.com
Fri Sep 12 09:15:38 UTC 2014
On Fri, Sep 12, 2014 at 10:57:26AM +0200, Michal Privoznik wrote:
> Up till bb3301ba the wrapper was freeing the passed strings for us.
> However that changed after the commit. So now we don't free any
> strings which results in memory leaks as reported upstream [1]:
>
> ==14265== 2,407 bytes in 1 blocks are definitely lost in loss record 1,457 of 1,550
> ==14265== at 0x4C2845D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==14265== by 0x5C46624: xdr_string (in /usr/lib64/libc-2.17.so)
> ==14265== by 0xCFD9FCD: xdr_remote_nonnull_string (remote_protocol.c:31)
> ==14265== by 0xCFDC2C8: xdr_remote_domain_get_xml_desc_ret (remote_protocol.c:1617)
> ==14265== by 0xCFF0811: virNetMessageDecodePayload (virnetmessage.c:407)
> ==14265== by 0xCFE68FB: virNetClientProgramCall (virnetclientprogram.c:379)
> ==14265== by 0xCFBE8B1: callFull.isra.2 (remote_driver.c:6578)
> ==14265== by 0xCFC7F04: remoteDomainGetXMLDesc (remote_driver.c:6600)
> ==14265== by 0xCF8167C: virDomainGetXMLDesc (libvirt.c:4380)
> ==14265== by 0xCC2C4DF: libvirt_virDomainGetXMLDesc (libvirt.c:1141)
> ==14265== by 0x4F12B93: PyEval_EvalFrameEx (in /usr/lib64/libpython2.7.so.1.0)
> ==14265== by 0x4F141AC: PyEval_EvalCodeEx (in /usr/lib64/libpython2.7.so.1.0)
>
> The python documentation clearly advise us to call free() [2]. From
> an example in their docs:
>
> PyObject *res;
> char *buf = (char *) malloc(BUFSIZ); /* for I/O */
>
> if (buf == NULL)
> return PyErr_NoMemory();
> ...Do some I/O operation involving buf...
> res = PyString_FromString(buf);
> free(buf); /* malloc'ed */
> return res;
>
> Moreover, instead of using VIR_FREE() (which we are not exporting),
> I'll just go with bare free().
>
> 1: https://www.redhat.com/archives/libvir-list/2014-September/msg00736.html
> 2: https://docs.python.org/2/c-api/memory.html
>
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
>
> While the fix seems okay, for some reason I'm seeing another valgrind warning
> after the fix is applied:
>
> ==21247== Invalid read of size 4
> ==21247== at 0x4EBFB93: PyObject_Free (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4EB613E: insertdict_by_entry (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4EB7BAF: dict_set_item_by_hash_or_entry (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4EBC4CB: _PyModule_Clear (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F2916A: PyImport_Cleanup (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F34B0D: Py_Finalize (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F460A5: Py_Main (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x54462BF: (below main) (in /lib64/libc-2.19.so)
> ==21247== Address 0x69be020 is 2,016 bytes inside a block of size 4,390 free'd
> ==21247== at 0x4C2B5AC: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==21247== by 0x7F1EC2D: libvirt_virDomainGetXMLDesc (in /home/zippy/work/libvirt/libvirt-python.git/build/lib.linux-x86_64-2.7/libvirtmod.so)
> ==21247== by 0x4F180BB: PyEval_EvalFrameEx (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F199FF: PyEval_EvalCodeEx (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F18AB4: PyEval_EvalFrameEx (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F199FF: PyEval_EvalCodeEx (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F19AF8: PyEval_EvalCode (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F32EBE: run_mod (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F340E1: PyRun_FileExFlags (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F352E6: PyRun_SimpleFileExFlags (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x4F4670E: Py_Main (in /usr/lib64/libpython2.7.so.1.0)
> ==21247== by 0x54462BF: (below main) (in /lib64/libc-2.19.so)
>
> This happens when using our examples/dominfo.py.
>
>
> generator.py | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/generator.py b/generator.py
> index a798274..8ee046a 100755
> --- a/generator.py
> +++ b/generator.py
> @@ -708,12 +708,16 @@ def print_function_wrapper(module, name, output, export, include):
> else:
> c_call = "\n c_retval = %s(%s);\n" % (name, c_call)
> ret_convert = " py_retval = libvirt_%sWrap((%s) c_retval);\n" % (n,c)
> + if n == "charPtr":
> + ret_convert = ret_convert + " free(c_retval);\n"
> ret_convert = ret_convert + " return py_retval;\n"
> elif ret[0] in py_return_types:
> (f, t, n, c) = py_return_types[ret[0]]
> c_return = " %s c_retval;\n" % (ret[0])
> c_call = "\n c_retval = %s(%s);\n" % (name, c_call)
> ret_convert = " py_retval = libvirt_%sWrap((%s) c_retval);\n" % (n,c)
> + if n == "charPtr":
> + ret_convert = ret_convert + " free(c_retval);\n"
> ret_convert = ret_convert + " return py_retval;\n"
> else:
> if ret[0] in skipped_types:
ACK.
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list