lawrence_danna created this revision. lawrence_danna added reviewers: labath, jasonmolenda, JDevlieghere, vadimcn. Herald added a project: LLDB. Herald added a subscriber: lldb-commits. lawrence_danna added a comment.
thanks @vadimcn for pointing this out. The buffer protocol does not allow us to just call PyBuffer_Release and assume the buffer will still be there. Most things that implement the buffer protocol will let us get away with that, but not all. We need to release it at the end of the SWIG wrapper. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D77480 Files: lldb/bindings/python/python-typemaps.swig Index: lldb/bindings/python/python-typemaps.swig =================================================================== --- lldb/bindings/python/python-typemaps.swig +++ lldb/bindings/python/python-typemaps.swig @@ -488,39 +488,51 @@ } } +%inline %{ + +class Py_buffer_RAII { +public: + Py_buffer m_buffer = {}; + ~Py_buffer_RAII() { + if (m_buffer.obj) + PyBuffer_Release(&m_buffer); + } +}; + +%} + // These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i, // and fixed so they will not crash if PyObject_GetBuffer fails. // https://github.com/swig/swig/issues/1640 +// +// I've also moved the call to PyBuffer_Release to the end of the SWIG wrapper, +// doing it right away is not legal according to the python buffer protocol. %define %pybuffer_mutable_binary(TYPEMAP, SIZE) -%typemap(in) (TYPEMAP, SIZE) { +%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { int res; Py_ssize_t size = 0; void *buf = 0; - Py_buffer view; - res = PyObject_GetBuffer($input, &view, PyBUF_WRITABLE); + res = PyObject_GetBuffer($input, &view.m_buffer, PyBUF_WRITABLE); if (res < 0) { PyErr_Clear(); %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); } - size = view.len; - buf = view.buf; - PyBuffer_Release(&view); + size = view.m_buffer.len; + buf = view.m_buffer.buf; $1 = ($1_ltype) buf; $2 = ($2_ltype) (size/sizeof($*1_type)); } %enddef %define %pybuffer_binary(TYPEMAP, SIZE) -%typemap(in) (TYPEMAP, SIZE) { +%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { int res; Py_ssize_t size = 0; const void *buf = 0; - Py_buffer view; - res = PyObject_GetBuffer($input, &view, PyBUF_CONTIG_RO); + res = PyObject_GetBuffer($input, &view.m_buffer, PyBUF_CONTIG_RO); if (res < 0) { PyErr_Clear(); %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); } - size = view.len; - buf = view.buf; - PyBuffer_Release(&view); + size = view.m_buffer.len; + buf = view.m_buffer.buf; $1 = ($1_ltype) buf; $2 = ($2_ltype) (size / sizeof($*1_type)); }
Index: lldb/bindings/python/python-typemaps.swig =================================================================== --- lldb/bindings/python/python-typemaps.swig +++ lldb/bindings/python/python-typemaps.swig @@ -488,39 +488,51 @@ } } +%inline %{ + +class Py_buffer_RAII { +public: + Py_buffer m_buffer = {}; + ~Py_buffer_RAII() { + if (m_buffer.obj) + PyBuffer_Release(&m_buffer); + } +}; + +%} + // These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i, // and fixed so they will not crash if PyObject_GetBuffer fails. // https://github.com/swig/swig/issues/1640 +// +// I've also moved the call to PyBuffer_Release to the end of the SWIG wrapper, +// doing it right away is not legal according to the python buffer protocol. %define %pybuffer_mutable_binary(TYPEMAP, SIZE) -%typemap(in) (TYPEMAP, SIZE) { +%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { int res; Py_ssize_t size = 0; void *buf = 0; - Py_buffer view; - res = PyObject_GetBuffer($input, &view, PyBUF_WRITABLE); + res = PyObject_GetBuffer($input, &view.m_buffer, PyBUF_WRITABLE); if (res < 0) { PyErr_Clear(); %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); } - size = view.len; - buf = view.buf; - PyBuffer_Release(&view); + size = view.m_buffer.len; + buf = view.m_buffer.buf; $1 = ($1_ltype) buf; $2 = ($2_ltype) (size/sizeof($*1_type)); } %enddef %define %pybuffer_binary(TYPEMAP, SIZE) -%typemap(in) (TYPEMAP, SIZE) { +%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { int res; Py_ssize_t size = 0; const void *buf = 0; - Py_buffer view; - res = PyObject_GetBuffer($input, &view, PyBUF_CONTIG_RO); + res = PyObject_GetBuffer($input, &view.m_buffer, PyBUF_CONTIG_RO); if (res < 0) { PyErr_Clear(); %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); } - size = view.len; - buf = view.buf; - PyBuffer_Release(&view); + size = view.m_buffer.len; + buf = view.m_buffer.buf; $1 = ($1_ltype) buf; $2 = ($2_ltype) (size / sizeof($*1_type)); }
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits