This revision was automatically updated to reflect the committed changes.
Closed by commit rG0a07c9662e67: [lldb/python] Fix dangling Event and
CommandReturnObject references (authored by labath).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D116162/new/
https://reviews.llvm.org/D116162
Files:
lldb/bindings/python/python-swigsafecast.swig
lldb/bindings/python/python-wrapper.swig
lldb/test/API/commands/command/script/TestCommandScript.py
lldb/test/API/commands/command/script/persistence.py
Index: lldb/test/API/commands/command/script/persistence.py
===================================================================
--- lldb/test/API/commands/command/script/persistence.py
+++ lldb/test/API/commands/command/script/persistence.py
@@ -1,9 +1,11 @@
import lldb
debugger_copy = None
+result_copy = None
def save_debugger(debugger, command, context, result, internal_dict):
- global debugger_copy
+ global debugger_copy, result_copy
debugger_copy = debugger
+ result_copy = result
result.AppendMessage(str(debugger))
result.SetStatus(lldb.eReturnStatusSuccessFinishResult)
Index: lldb/test/API/commands/command/script/TestCommandScript.py
===================================================================
--- lldb/test/API/commands/command/script/TestCommandScript.py
+++ lldb/test/API/commands/command/script/TestCommandScript.py
@@ -167,7 +167,17 @@
self.runCmd('bug11569', check=False)
def test_persistence(self):
+ """
+ Ensure that function arguments meaningfully persist (and do not crash!)
+ even after the function terminates.
+ """
self.runCmd("command script import persistence.py")
self.runCmd("command script add -f persistence.save_debugger save_debugger")
self.expect("save_debugger", substrs=[str(self.dbg)])
+
+ # After the command completes, the debugger object should still be
+ # valid.
self.expect("script str(persistence.debugger_copy)", substrs=[str(self.dbg)])
+ # The result object will be replaced by an empty result object (in the
+ # "Started" state).
+ self.expect("script str(persistence.result_copy)", substrs=["Started"])
Index: lldb/bindings/python/python-wrapper.swig
===================================================================
--- lldb/bindings/python/python-wrapper.swig
+++ lldb/bindings/python/python-wrapper.swig
@@ -376,9 +376,8 @@
PythonObject result;
if (event != nullptr) {
- lldb::SBEvent sb_event(event);
- PythonObject event_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_event));
- result = pfunc(event_arg);
+ ScopedPythonObject<SBEvent> event_arg = ToSWIGWrapper(event);
+ result = pfunc(event_arg.obj());
} else
result = pfunc();
@@ -795,7 +794,6 @@
lldb::DebuggerSP debugger, const char *args,
lldb_private::CommandReturnObject &cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp) {
- lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj);
PyErr_Cleaner py_err_cleaner(true);
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
@@ -812,14 +810,13 @@
return false;
}
PythonObject debugger_arg = ToSWIGWrapper(std::move(debugger));
- PythonObject cmd_retobj_arg(PyRefType::Owned,
- SBTypeToSWIGWrapper(cmd_retobj_sb));
+ auto cmd_retobj_arg = ToSWIGWrapper(cmd_retobj);
if (argc.get().max_positional_args < 5u)
- pfunc(debugger_arg, PythonString(args), cmd_retobj_arg, dict);
+ pfunc(debugger_arg, PythonString(args), cmd_retobj_arg.obj(), dict);
else
pfunc(debugger_arg, PythonString(args),
- ToSWIGWrapper(std::move(exe_ctx_ref_sp)), cmd_retobj_arg, dict);
+ ToSWIGWrapper(std::move(exe_ctx_ref_sp)), cmd_retobj_arg.obj(), dict);
return true;
}
@@ -828,7 +825,6 @@
PyObject *implementor, lldb::DebuggerSP debugger, const char *args,
lldb_private::CommandReturnObject &cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp) {
- lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj);
PyErr_Cleaner py_err_cleaner(true);
@@ -838,11 +834,10 @@
if (!pfunc.IsAllocated())
return false;
- PythonObject cmd_retobj_arg(PyRefType::Owned,
- SBTypeToSWIGWrapper(cmd_retobj_sb));
+ auto cmd_retobj_arg = ToSWIGWrapper(cmd_retobj);
pfunc(ToSWIGWrapper(std::move(debugger)), PythonString(args),
- ToSWIGWrapper(exe_ctx_ref_sp), cmd_retobj_arg);
+ ToSWIGWrapper(exe_ctx_ref_sp), cmd_retobj_arg.obj());
return true;
}
Index: lldb/bindings/python/python-swigsafecast.swig
===================================================================
--- lldb/bindings/python/python-swigsafecast.swig
+++ lldb/bindings/python/python-swigsafecast.swig
@@ -1,19 +1,32 @@
namespace lldb_private {
namespace python {
-PyObject *SBTypeToSWIGWrapper(lldb::SBEvent &event_sb) {
- return SWIG_NewPointerObj(&event_sb, SWIGTYPE_p_lldb__SBEvent, 0);
-}
-
-PyObject *SBTypeToSWIGWrapper(lldb::SBCommandReturnObject &cmd_ret_obj_sb) {
- return SWIG_NewPointerObj(&cmd_ret_obj_sb,
- SWIGTYPE_p_lldb__SBCommandReturnObject, 0);
-}
-
PythonObject ToSWIGHelper(void *obj, swig_type_info *info) {
return {PyRefType::Owned, SWIG_NewPointerObj(obj, info, SWIG_POINTER_OWN)};
}
+/// A class that automatically clears an SB object when it goes out of scope.
+/// Use for cases where the SB object points to a temporary/unowned entity.
+template <typename T> class ScopedPythonObject : PythonObject {
+public:
+ ScopedPythonObject(T *sb, swig_type_info *info)
+ : PythonObject(ToSWIGHelper(sb, info)), m_sb(sb) {}
+ ~ScopedPythonObject() {
+ if (m_sb)
+ *m_sb = T();
+ }
+ ScopedPythonObject(ScopedPythonObject &&rhs)
+ : PythonObject(std::move(rhs)), m_sb(std::exchange(rhs.m_sb, nullptr)) {}
+ ScopedPythonObject(const ScopedPythonObject &) = delete;
+ ScopedPythonObject &operator=(const ScopedPythonObject &) = delete;
+ ScopedPythonObject &operator=(ScopedPythonObject &&) = delete;
+
+ const PythonObject &obj() const { return *this; }
+
+private:
+ T *m_sb;
+};
+
PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBValue> value_sb) {
return ToSWIGHelper(value_sb.release(), SWIGTYPE_p_lldb__SBValue);
}
@@ -94,5 +107,17 @@
SWIGTYPE_p_lldb__SBSymbolContext);
}
+ScopedPythonObject<lldb::SBCommandReturnObject>
+ToSWIGWrapper(CommandReturnObject &cmd_retobj) {
+ return ScopedPythonObject<lldb::SBCommandReturnObject>(
+ new lldb::SBCommandReturnObject(cmd_retobj),
+ SWIGTYPE_p_lldb__SBCommandReturnObject);
+}
+
+ScopedPythonObject<lldb::SBEvent> ToSWIGWrapper(Event *event) {
+ return ScopedPythonObject<lldb::SBEvent>(new lldb::SBEvent(event),
+ SWIGTYPE_p_lldb__SBEvent);
+}
+
} // namespace python
} // namespace lldb_private
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits