Index: include/lldb/Target/Process.h =================================================================== --- include/lldb/Target/Process.h +++ include/lldb/Target/Process.h @@ -1248,7 +1248,13 @@ /// @return /// Returns an error object. //------------------------------------------------------------------ - virtual Status WillResume() { return Status(); } + virtual Status WillResume() { + Status error; + error.SetErrorStringWithFormat( + "error: %s does not support resuming processes", + GetPluginName().GetCString()); + return error; + } //------------------------------------------------------------------ /// Resumes all of a process's threads as configured using the Index: packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py +++ packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -244,6 +244,34 @@ end_region.GetRegionBase()) self.assertEqual(end_region.GetRegionEnd(), lldb.LLDB_INVALID_ADDRESS) + def check_state(self, process): + with open(os.devnull) as devnul: + # sanitize test output + self.dbg.SetOutputFileHandle(devnul, False) + self.dbg.SetErrorFileHandle(devnul, False) + + self.assertTrue(process.is_stopped) + + # Process.Continue + error = process.Continue() + self.assertFalse(error.Success()) + self.assertTrue(process.is_stopped) + + # Thread.StepOut + thread = process.GetSelectedThread() + thread.StepOut() + self.assertTrue(process.is_stopped) + + # command line + self.dbg.HandleCommand('s') + self.assertTrue(process.is_stopped) + self.dbg.HandleCommand('c') + self.assertTrue(process.is_stopped) + + # restore file handles + self.dbg.SetOutputFileHandle(None, False) + self.dbg.SetErrorFileHandle(None, False) + def do_test(self, filename, pid, region_count): target = self.dbg.CreateTarget(filename + ".out") process = target.LoadCore(filename + ".core") @@ -251,6 +279,8 @@ self.assertEqual(process.GetNumThreads(), 1) self.assertEqual(process.GetProcessID(), pid) + self.check_state(process) + thread = process.GetSelectedThread() self.assertTrue(thread) self.assertEqual(thread.GetThreadID(), pid) Index: packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py +++ packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py @@ -31,6 +31,34 @@ lldb.DBG.SetSelectedPlatform(self._initial_platform) super(MiniDumpNewTestCase, self).tearDown() + def check_state(self): + with open(os.devnull) as devnul: + # sanitize test output + self.dbg.SetOutputFileHandle(devnul, False) + self.dbg.SetErrorFileHandle(devnul, False) + + self.assertTrue(self.process.is_stopped) + + # Process.Continue + error = self.process.Continue() + self.assertFalse(error.Success()) + self.assertTrue(self.process.is_stopped) + + # Thread.StepOut + thread = self.process.GetSelectedThread() + thread.StepOut() + self.assertTrue(self.process.is_stopped) + + # command line + self.dbg.HandleCommand('s') + self.assertTrue(self.process.is_stopped) + self.dbg.HandleCommand('c') + self.assertTrue(self.process.is_stopped) + + # restore file handles + self.dbg.SetOutputFileHandle(None, False) + self.dbg.SetErrorFileHandle(None, False) + def test_process_info_in_minidump(self): """Test that lldb can read the process information from the Minidump.""" # target create -c linux-x86_64.dmp @@ -40,6 +68,7 @@ self.assertTrue(self.process, PROCESS_IS_VALID) self.assertEqual(self.process.GetNumThreads(), 1) self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid) + self.check_state() def test_thread_info_in_minidump(self): """Test that lldb can read the thread information from the Minidump.""" @@ -47,6 +76,7 @@ self.dbg.CreateTarget(None) self.target = self.dbg.GetSelectedTarget() self.process = self.target.LoadCore("linux-x86_64.dmp") + self.check_state() # This process crashed due to a segmentation fault in its # one and only thread. self.assertEqual(self.process.GetNumThreads(), 1) @@ -61,6 +91,7 @@ self.dbg.CreateTarget("linux-x86_64") self.target = self.dbg.GetSelectedTarget() self.process = self.target.LoadCore("linux-x86_64.dmp") + self.check_state() self.assertEqual(self.process.GetNumThreads(), 1) self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid) thread = self.process.GetThreadAtIndex(0) @@ -81,6 +112,7 @@ self.dbg.CreateTarget(None) self.target = self.dbg.GetSelectedTarget() self.process = self.target.LoadCore("linux-x86_64_not_crashed.dmp") + self.check_state() self.assertEqual(self.process.GetNumThreads(), 1) thread = self.process.GetThreadAtIndex(0) self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone) @@ -161,9 +193,10 @@ """Test that we can examine local variables in a Minidump.""" # Launch with the Minidump, and inspect a local variable. # target create linux-x86_64_not_crashed -c linux-x86_64_not_crashed.dmp - target = self.dbg.CreateTarget("linux-x86_64_not_crashed") - process = target.LoadCore("linux-x86_64_not_crashed.dmp") - thread = process.GetThreadAtIndex(0) + self.target = self.dbg.CreateTarget("linux-x86_64_not_crashed") + self.process = self.target.LoadCore("linux-x86_64_not_crashed.dmp") + self.check_state() + thread = self.process.GetThreadAtIndex(0) frame = thread.GetFrameAtIndex(1) value = frame.EvaluateExpression('x') self.assertEqual(value.GetValueAsSigned(), 3) Index: source/Commands/CommandObjectThread.cpp =================================================================== --- source/Commands/CommandObjectThread.cpp +++ source/Commands/CommandObjectThread.cpp @@ -94,7 +94,7 @@ bool all_threads = false; if (command.GetArgumentCount() == 0) { Thread *thread = m_exe_ctx.GetThreadPtr(); - if (!HandleOneThread(thread->GetID(), result)) + if (!thread || !HandleOneThread(thread->GetID(), result)) return false; return result.Succeeded(); } else if (command.GetArgumentCount() == 1) { @@ -775,6 +775,12 @@ else error = process->Resume(); + if (!error.Success()) { + result.AppendMessage(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + // There is a race condition where this thread will return up the call // stack to the main command handler // and show an (lldb) prompt before HandlePrivateEvent (from Index: source/Plugins/Process/elf-core/ProcessElfCore.h =================================================================== --- source/Plugins/Process/elf-core/ProcessElfCore.h +++ source/Plugins/Process/elf-core/ProcessElfCore.h @@ -89,6 +89,8 @@ //------------------------------------------------------------------ bool IsAlive() override; + bool WarnBeforeDetach() const override { return false; } + //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ Index: source/Target/Process.cpp =================================================================== --- source/Target/Process.cpp +++ source/Target/Process.cpp @@ -1621,7 +1621,12 @@ log->Printf("Process::Resume: -- TrySetRunning failed, not resuming."); return error; } - return PrivateResume(); + Status error = PrivateResume(); + if (!error.Success()) { + // Undo running state change + m_public_run_lock.SetStopped(); + } + return error; } Status Process::ResumeSynchronous(Stream *stream) { @@ -1650,6 +1655,9 @@ error.SetErrorStringWithFormat( "process not in stopped state after synchronous resume: %s", StateAsCString(state)); + } else { + // Undo running state change + m_public_run_lock.SetStopped(); } // Undo the hijacking of process events...