diff --git a/lldb/test/tools/lldb-mi/control/TestMiExec.py b/lldb/test/tools/lldb-mi/control/TestMiExec.py index 7ab479d3b30d..97f7fe4ede42 100644 --- a/lldb/test/tools/lldb-mi/control/TestMiExec.py +++ b/lldb/test/tools/lldb-mi/control/TestMiExec.py @@ -12,7 +12,7 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase): @lldbmi_test @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") - @unittest2.skip("-exec-abort isn't implemented") + @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_exec_abort(self): """Test that 'lldb-mi --interpreter' works for -exec-abort.""" diff --git a/lldb/tools/lldb-mi/MICmdCmdExec.cpp b/lldb/tools/lldb-mi/MICmdCmdExec.cpp index 9b5fbbfb396d..20d0fcde5e81 100644 --- a/lldb/tools/lldb-mi/MICmdCmdExec.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdExec.cpp @@ -19,6 +19,7 @@ // CMICmdCmdExecFinish implementation. // CMICmdCmdExecInterrupt implementation. // CMICmdCmdExecArguments implementation. +// CMICmdCmdExecAbort implementation. // // Environment: Compilers: Visual C++ 12. // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 @@ -1136,3 +1137,95 @@ CMICmdCmdExecArguments::CreateSelf(void) { return new CMICmdCmdExecArguments(); } + +//--------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------- + +//++ ------------------------------------------------------------------------------------ +// Details: CMICmdCmdExecAbort constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. +//-- +CMICmdCmdExecAbort::CMICmdCmdExecAbort(void) +{ + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-abort"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecAbort::CreateSelf; +} + +//++ ------------------------------------------------------------------------------------ +// Details: CMICmdCmdExecAbort destructor. +// Type: Overrideable. +// Args: None. +// Return: None. +// Throws: None. +//-- +CMICmdCmdExecAbort::~CMICmdCmdExecAbort(void) +{ +} + +//++ ------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this function. +// The command is likely to communicate with the LLDB SBDebugger in here. +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Function succeeded. +// MIstatus::failure - Function failed. +// Throws: None. +//-- +bool +CMICmdCmdExecAbort::Execute(void) +{ + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + if (!sbProcess.IsValid()) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + lldb::SBError sbError = sbProcess.Destroy(); + if (sbError.Fail()) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDBPROCESS_DESTROY), m_cmdData.strMiCmd.c_str(), sbError.GetCString())); + return MIstatus::failure; + } + + return MIstatus::success; +} + +//++ ------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record Result +// for the work carried out in the Execute(). +// Type: Overridden. +// Args: None. +// Return: MIstatus::success - Function succeeded. +// MIstatus::failure - Function failed. +// Throws: None. +//-- +bool +CMICmdCmdExecAbort::Acknowledge(void) +{ + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + return MIstatus::success; +} + +//++ ------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Static method. +// Args: None. +// Return: CMICmdBase * - Pointer to a new command. +// Throws: None. +//-- +CMICmdBase * +CMICmdCmdExecAbort::CreateSelf(void) +{ + return new CMICmdCmdExecAbort(); +} diff --git a/lldb/tools/lldb-mi/MICmdCmdExec.h b/lldb/tools/lldb-mi/MICmdCmdExec.h index 1a3e749972c8..1a1281f086ad 100644 --- a/lldb/tools/lldb-mi/MICmdCmdExec.h +++ b/lldb/tools/lldb-mi/MICmdCmdExec.h @@ -19,6 +19,7 @@ // CMICmdCmdExecFinish interface. // CMICmdCmdExecInterrupt interface. // CMICmdCmdExecArguments interface. +// CMICmdCmdExecAbort interface. // // To implement new MI commands derive a new command class from the command base // class. To enable the new command for interpretation add the new command class @@ -340,3 +341,27 @@ class CMICmdCmdExecArguments : public CMICmdBase private: const CMIUtilString m_constStrArgArguments; }; + +//++ ============================================================================ +// Details: MI command class. MI commands derived from the command base class. +// *this class implements MI command "exec-abort". +//-- +class CMICmdCmdExecAbort : public CMICmdBase +{ + // Statics: + public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(void); + + // Methods: + public: + /* ctor */ CMICmdCmdExecAbort(void); + + // Overridden: + public: + // From CMICmdInvoker::ICmd + virtual bool Execute(void); + virtual bool Acknowledge(void); + // From CMICmnBase + /* dtor */ virtual ~CMICmdCmdExecAbort(void); +}; diff --git a/lldb/tools/lldb-mi/MICmdCommands.cpp b/lldb/tools/lldb-mi/MICmdCommands.cpp index a2e10d1a2c41..772311d99f7c 100644 --- a/lldb/tools/lldb-mi/MICmdCommands.cpp +++ b/lldb/tools/lldb-mi/MICmdCommands.cpp @@ -99,6 +99,7 @@ MICmnCommands::RegisterAll(void) bOk &= Register(); bOk &= Register(); bOk &= Register(); + bOk &= Register(); bOk &= Register(); bOk &= Register(); bOk &= Register(); diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp b/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp index 37ddda4db0ce..d1452e9fe706 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp @@ -663,13 +663,12 @@ CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive) m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s", event.GetBroadcasterClass())); bool bHandledEvent = false; - bool bExitAppEvent = false; bool bOk = false; { // Lock Mutex before handling events so that we don't disturb a running cmd CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); - bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent, bExitAppEvent); + bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent); } if (!bHandledEvent) { @@ -681,15 +680,6 @@ CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive) m_pLog->WriteLog(CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription()); } - if (bExitAppEvent) - { - // Set the application to shutdown - m_pClientDriver->SetExitApplicationFlag(true); - - // Kill *this thread - vrbIsAlive = false; - } - return bOk; } diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp index 2c7f74675752..847adf125e3c 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp @@ -126,22 +126,20 @@ CMICmnLLDBDebuggerHandleEvents::Shutdown(void) // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. // vrbHandledEvent - (W) True - event handled, false = not handled. -// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool -CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent, bool &vrbExitAppEvent) +CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent) { bool bOk = MIstatus::success; vrbHandledEvent = false; - vrbExitAppEvent = false; if (lldb::SBProcess::EventIsProcessEvent(vEvent)) { vrbHandledEvent = true; - bOk = HandleEventSBProcess(vEvent, vrbExitAppEvent); + bOk = HandleEventSBProcess(vEvent); } else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent)) { @@ -161,13 +159,12 @@ CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &v // Details: Handle a LLDB SBProcess event. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. -// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent) +CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent) { bool bOk = MIstatus::success; @@ -183,7 +180,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent break; case lldb::SBProcess::eBroadcastBitStateChanged: pEventType = "eBroadcastBitStateChanged"; - bOk = HandleProcessEventBroadcastBitStateChanged(vEvent, vrbExitAppEvent); + bOk = HandleProcessEventBroadcastBitStateChanged(vEvent); break; case lldb::SBProcess::eBroadcastBitSTDERR: pEventType = "eBroadcastBitSTDERR"; @@ -627,13 +624,12 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEv // Details: Handle SBProcess event eBroadcastBitStateChanged. // Type: Method. // Args: vEvent - (R) An LLDB event object. -// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent) +CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent) { bool bOk = ChkForStateChanges(); bOk = bOk && GetProcessStdout(); @@ -693,8 +689,8 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const pEventType = "eStateDetached"; break; case lldb::eStateExited: + // Don't exit from lldb-mi here. We should be able to re-run target. pEventType = "eStateExited"; - vrbExitAppEvent = true; bOk = HandleProcessEventStateExited(); break; default: diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h index dec8b23f0e4a..5fe9af1a39c1 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h +++ b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h @@ -50,7 +50,7 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton< bool Initialize(void); bool Shutdown(void); // - bool HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent, bool &vrbExitAppEvent); + bool HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent); // Methods: private: @@ -65,12 +65,12 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton< bool HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent); bool HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent); bool HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent); - bool HandleEventSBProcess(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent); + bool HandleEventSBProcess(const lldb::SBEvent &vEvent); bool HandleEventSBThread(const lldb::SBEvent &vEvent); bool HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent); bool HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent); bool HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent); - bool HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent); + bool HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent); bool HandleProcessEventStateRunning(void); bool HandleProcessEventStateExited(void); bool HandleProcessEventStateStopped(bool &vwrbShouldBrk); diff --git a/lldb/tools/lldb-mi/MICmnResources.cpp b/lldb/tools/lldb-mi/MICmnResources.cpp index bc1fa3025cd6..84179bb0121b 100644 --- a/lldb/tools/lldb-mi/MICmnResources.cpp +++ b/lldb/tools/lldb-mi/MICmnResources.cpp @@ -225,6 +225,7 @@ const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[] {IDS_CMD_ERR_FNFAILED, "Command '%s'. Fn '%s' failed"}, {IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, "Command '%s'. Shared data '%s' not found"}, {IDS_CMD_ERR_LLDBPROCESS_DETACH, "Command '%s'. Process detach failed. '%s'"}, + {IDS_CMD_ERR_LLDBPROCESS_DESTROY, "Command '%s'. Process destroy failed. '%s'"}, {IDS_CMD_ERR_SETWKDIR, "Command '%s'. Failed to set working directory '%s'"}, {IDS_CMD_ERR_INVALID_TARGET, "Command '%s'. Target binary '%s' is invalid. %s"}, {IDS_CMD_ERR_INVALID_TARGET_CURRENT, "Command '%s'. Current SBTarget is invalid"}, diff --git a/lldb/tools/lldb-mi/MICmnResources.h b/lldb/tools/lldb-mi/MICmnResources.h index b561473fbb79..b02c9c6fea62 100644 --- a/lldb/tools/lldb-mi/MICmnResources.h +++ b/lldb/tools/lldb-mi/MICmnResources.h @@ -241,6 +241,7 @@ enum IDS_CMD_ERR_FNFAILED, IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, IDS_CMD_ERR_LLDBPROCESS_DETACH, + IDS_CMD_ERR_LLDBPROCESS_DESTROY, IDS_CMD_ERR_SETWKDIR, IDS_CMD_ERR_INVALID_TARGET, IDS_CMD_ERR_INVALID_TARGET_CURRENT,