Index: lldb/include/lldb/API/SBCommandReturnObject.h =================================================================== --- lldb/include/lldb/API/SBCommandReturnObject.h +++ lldb/include/lldb/API/SBCommandReturnObject.h @@ -15,6 +15,17 @@ #include "lldb/API/SBDefines.h" +namespace lldb { +class LLDB_API SBCommandReturnObject; +} + +namespace lldb_private { +// Wrap SBCommandReturnObject::ref() so that any LLDB internal function can +// call it but still no SB API users can call it. +CommandReturnObject & +SBCommandReturnObject_ref(lldb::SBCommandReturnObject &sb_cmd); +} // namespace lldb_private + namespace lldb { class LLDB_API SBCommandReturnObject { @@ -28,10 +39,6 @@ const lldb::SBCommandReturnObject & operator=(const lldb::SBCommandReturnObject &rhs); - SBCommandReturnObject(lldb_private::CommandReturnObject *ptr); - - lldb_private::CommandReturnObject *Release(); - explicit operator bool() const; bool IsValid() const; @@ -89,6 +96,8 @@ protected: friend class SBCommandInterpreter; friend class SBOptions; + friend lldb_private::CommandReturnObject & + lldb_private::SBCommandReturnObject_ref(SBCommandReturnObject &sb_cmd); lldb_private::CommandReturnObject *operator->() const; Index: lldb/packages/Python/lldbsuite/test/api/command-return-object/Makefile =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/api/command-return-object/Makefile @@ -0,0 +1,5 @@ +MAKE_DSYM := NO + +CXX_SOURCES := main.cpp + +include Makefile.rules Index: lldb/packages/Python/lldbsuite/test/api/command-return-object/TestSBCommandReturnObject.py =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/api/command-return-object/TestSBCommandReturnObject.py @@ -0,0 +1,31 @@ +"""Test the lldb public C++ api for returning SBCommandReturnObject.""" + +from __future__ import print_function + + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestSBCommandReturnObject(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + @skipIfNoSBHeaders + def test_sb_command_return_object(self): + env = {self.dylibPath: self.getLLDBLibraryEnvVal()} + + self.driver_exe = self.getBuildArtifact("command-return-object") + self.buildDriver('main.cpp', self.driver_exe) + self.addTearDownHook(lambda: os.remove(self.driver_exe)) + self.signBinary(self.driver_exe) + + if self.TraceOn(): + print("Running test %s" % self.driver_exe) + check_call([self.driver_exe, self.driver_exe], env=env) + else: + with open(os.devnull, 'w') as fnull: + check_call([self.driver_exe, self.driver_exe], + env=env, stdout=fnull, stderr=fnull) Index: lldb/packages/Python/lldbsuite/test/api/command-return-object/main.cpp =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/api/command-return-object/main.cpp @@ -0,0 +1,33 @@ +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBDebugger.h" + +using namespace lldb; + +static SBCommandReturnObject subcommand(SBDebugger &dbg, const char *cmd) { + SBCommandReturnObject Result; + dbg.GetCommandInterpreter().HandleCommand(cmd, Result); + return Result; +} + +class CommandCrasher : public SBCommandPluginInterface { +public: + bool DoExecute(SBDebugger dbg, char **command, + SBCommandReturnObject &result) { + result = subcommand(dbg, "help"); + result = result; + if (!result.Succeeded()) + return false; + return true; + } +}; + +int main() { + SBDebugger::Initialize(); + SBDebugger dbg = SBDebugger::Create(false /*source_init_files*/); + SBCommandInterpreter interp = dbg.GetCommandInterpreter(); + static CommandCrasher crasher; + interp.AddCommand("crasher", &crasher, nullptr /*help*/); + SBCommandReturnObject Result; + dbg.GetCommandInterpreter().HandleCommand("crasher", Result); +} Index: lldb/scripts/Python/python-wrapper.swig =================================================================== --- lldb/scripts/Python/python-wrapper.swig +++ lldb/scripts/Python/python-wrapper.swig @@ -650,30 +650,6 @@ return sb_ptr; } -// Currently, SBCommandReturnObjectReleaser wraps a unique pointer to an -// lldb_private::CommandReturnObject. This means that the destructor for the -// SB object will deallocate its contained CommandReturnObject. Because that -// object is used as the real return object for Python-based commands, we want -// it to stay around. Thus, we release the unique pointer before returning from -// LLDBSwigPythonCallCommand, and to guarantee that the release will occur no -// matter how we exit from the function, we have a releaser object whose -// destructor does the right thing for us -class SBCommandReturnObjectReleaser -{ -public: - SBCommandReturnObjectReleaser (lldb::SBCommandReturnObject &obj) : - m_command_return_object_ref (obj) - { - } - - ~SBCommandReturnObjectReleaser () - { - m_command_return_object_ref.Release(); - } -private: - lldb::SBCommandReturnObject &m_command_return_object_ref; -}; - SWIGEXPORT bool LLDBSwigPythonCallCommand ( @@ -686,8 +662,8 @@ ) { using namespace lldb_private; - lldb::SBCommandReturnObject cmd_retobj_sb(&cmd_retobj); - SBCommandReturnObjectReleaser cmd_retobj_sb_releaser(cmd_retobj_sb); + lldb::SBCommandReturnObject cmd_retobj_sb; + std::swap(cmd_retobj, SBCommandReturnObject_ref(cmd_retobj_sb)); lldb::SBDebugger debugger_sb(debugger); lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp); @@ -710,6 +686,7 @@ else pfunc(debugger_arg, PythonString(args), cmd_retobj_arg, dict); + std::swap(cmd_retobj, SBCommandReturnObject_ref(cmd_retobj_sb)); return true; } @@ -724,8 +701,8 @@ ) { using namespace lldb_private; - lldb::SBCommandReturnObject cmd_retobj_sb(&cmd_retobj); - SBCommandReturnObjectReleaser cmd_retobj_sb_releaser(cmd_retobj_sb); + lldb::SBCommandReturnObject cmd_retobj_sb; + std::swap(cmd_retobj, SBCommandReturnObject_ref(cmd_retobj_sb)); lldb::SBDebugger debugger_sb(debugger); lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp); @@ -745,6 +722,7 @@ pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg); + std::swap(cmd_retobj, SBCommandReturnObject_ref(cmd_retobj_sb)); return true; } @@ -1041,6 +1019,7 @@ // Forward declaration to be inserted at the start of LLDBWrapPython.h #include "lldb/API/SBDebugger.h" #include "lldb/API/SBValue.h" +#include "lldb/Interpreter/CommandReturnObject.h" SWIGEXPORT lldb::ValueObjectSP LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data) Index: lldb/source/API/SBCommandInterpreter.cpp =================================================================== --- lldb/source/API/SBCommandInterpreter.cpp +++ lldb/source/API/SBCommandInterpreter.cpp @@ -162,12 +162,13 @@ protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - SBCommandReturnObject sb_return(&result); + SBCommandReturnObject sb_return; + std::swap(result, SBCommandReturnObject_ref(sb_return)); SBCommandInterpreter sb_interpreter(&m_interpreter); SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); bool ret = m_backend->DoExecute( debugger_sb, (char **)command.GetArgumentVector(), sb_return); - sb_return.Release(); + std::swap(result, SBCommandReturnObject_ref(sb_return)); return ret; } std::shared_ptr m_backend; Index: lldb/source/API/SBCommandReturnObject.cpp =================================================================== --- lldb/source/API/SBCommandReturnObject.cpp +++ lldb/source/API/SBCommandReturnObject.cpp @@ -18,6 +18,11 @@ using namespace lldb; using namespace lldb_private; +lldb_private::CommandReturnObject & +lldb_private::SBCommandReturnObject_ref(SBCommandReturnObject &sb_cmd) { + return sb_cmd.ref(); +} + SBCommandReturnObject::SBCommandReturnObject() : m_opaque_up(new CommandReturnObject()) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommandReturnObject); @@ -31,21 +36,8 @@ m_opaque_up = clone(rhs.m_opaque_up); } -SBCommandReturnObject::SBCommandReturnObject(CommandReturnObject *ptr) - : m_opaque_up(ptr) { - LLDB_RECORD_CONSTRUCTOR(SBCommandReturnObject, - (lldb_private::CommandReturnObject *), ptr); -} - SBCommandReturnObject::~SBCommandReturnObject() = default; -CommandReturnObject *SBCommandReturnObject::Release() { - LLDB_RECORD_METHOD_NO_ARGS(lldb_private::CommandReturnObject *, - SBCommandReturnObject, Release); - - return LLDB_RECORD_RESULT(m_opaque_up.release()); -} - const SBCommandReturnObject &SBCommandReturnObject:: operator=(const SBCommandReturnObject &rhs) { LLDB_RECORD_METHOD( @@ -338,10 +330,6 @@ LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, ()); LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, (const lldb::SBCommandReturnObject &)); - LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, - (lldb_private::CommandReturnObject *)); - LLDB_REGISTER_METHOD(lldb_private::CommandReturnObject *, - SBCommandReturnObject, Release, ()); LLDB_REGISTER_METHOD( const lldb::SBCommandReturnObject &, SBCommandReturnObject, operator=,(const lldb::SBCommandReturnObject &));