diff options
| -rw-r--r-- | lldb/include/lldb/Target/Process.h | 5 | ||||
| -rw-r--r-- | lldb/source/Target/ExecutionContext.cpp | 6 | ||||
| -rw-r--r-- | lldb/source/Target/Process.cpp | 3 | ||||
| -rw-r--r-- | lldb/test/functionalities/signal/TestSendSignal.py | 96 |
4 files changed, 71 insertions, 39 deletions
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index e04de511c79..3308d161994 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -678,13 +678,16 @@ public: bool IsLastResumeForUserExpression () const { + // If we haven't yet resumed the target, then it can't be for a user expression... + if (m_resume_id == 0) + return false; + return m_resume_id == m_last_user_expression_resume; } void SetRunningUserExpression (bool on) { - // REMOVEME printf ("Setting running user expression %s at resume id %d - value: %d.\n", on ? "on" : "off", m_resume_id, m_running_user_expression); if (on) m_running_user_expression++; else diff --git a/lldb/source/Target/ExecutionContext.cpp b/lldb/source/Target/ExecutionContext.cpp index db4025f40c0..e03a560bd06 100644 --- a/lldb/source/Target/ExecutionContext.cpp +++ b/lldb/source/Target/ExecutionContext.cpp @@ -705,7 +705,11 @@ ExecutionContextRef::SetTargetPtr (Target* target, bool adopt_selected) if (process_sp) { // Only fill in the thread and frame if our process is stopped - if (StateIsStoppedState (process_sp->GetState(), true)) + // Don't just check the state, since we might be in the middle of + // resuming. + Process::StopLocker stop_locker; + + if (stop_locker.TryLock(&process_sp->GetRunLock()) && StateIsStoppedState (process_sp->GetState(), true)) { lldb::ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); if (!thread_sp) diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 106678da268..50d2b5afcf6 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -3643,7 +3643,8 @@ Process::PrivateResume () } else { - // Somebody wanted to run without running. So generate a continue & a stopped event, + // Somebody wanted to run without running (e.g. we were faking a step from one frame of a set of inlined + // frames that share the same PC to another.) So generate a continue & a stopped event, // and let the world handle them. if (log) log->Printf ("Process::PrivateResume() asked to simulate a start & stop."); diff --git a/lldb/test/functionalities/signal/TestSendSignal.py b/lldb/test/functionalities/signal/TestSendSignal.py index f5868291468..4dac5e9000d 100644 --- a/lldb/test/functionalities/signal/TestSendSignal.py +++ b/lldb/test/functionalities/signal/TestSendSignal.py @@ -33,51 +33,75 @@ class SendSignalTestCase(TestBase): """Test that lldb command 'process signal SIGUSR1' sends a signal to the inferior process.""" exe = os.path.join(os.getcwd(), "a.out") - self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) - # Break inside the main() function and immediately send a signal to the inferior after resuming. - lldbutil.run_break_set_by_file_and_line (self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByLocation ('main.c', self.line) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Now launch the process, no arguments & do not stop at entry point. + launch_info = lldb.SBLaunchInfo([exe]) + launch_info.SetWorkingDirectory(self.get_process_working_directory()) + + process_listener = lldb.SBListener("signal_test_listener") + launch_info.SetListener(process_listener) + error = lldb.SBError() + process = target.Launch (launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) - self.runCmd("run", RUN_SUCCEEDED) - self.runCmd("thread backtrace") + self.runCmd("process handle -n False -p True -s True SIGUSR1") - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs = ['stopped', - 'stop reason = breakpoint']) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "We hit the first breakpoint.") - # The breakpoint should have a hit count of 1. - self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, - substrs = [' resolved, hit count = 1']) + # After resuming the process, send it a SIGUSR1 signal. - self.runCmd("process status") - output = self.res.GetOutput() - pid = re.match("Process (.*) stopped", output).group(1) + self.setAsync(True) - # After resuming the process, send it a SIGUSR1 signal. + broadcaster = process.GetBroadcaster() - # It is necessary at this point to make command interpreter interaction - # be asynchronous, because we want to resume the process and to send it - # a signal. - self.dbg.SetAsync(True) - self.runCmd("process continue") - # Insert a delay of 1 second before doing the signaling stuffs. - time.sleep(1) + self.assertTrue(process_listener.IsValid(), "Got a good process listener") - self.runCmd("process handle -n False -p True -s True SIGUSR1") - #os.kill(int(pid), signal.SIGUSR1) - self.runCmd("process signal SIGUSR1") - - # Insert a delay of 1 second before checking the process status. - time.sleep(1) - # Make the interaction mode be synchronous again. - self.dbg.SetAsync(False) - self.expect("process status", STOPPED_DUE_TO_SIGNAL, - startstr = "Process %s stopped" % pid, - substrs = ['stop reason = signal SIGUSR1']) - self.expect("thread backtrace", STOPPED_DUE_TO_SIGNAL, - substrs = ['stop reason = signal SIGUSR1']) + # Disable our breakpoint, we don't want to hit it anymore... + breakpoint.SetEnabled(False) + + # Now continue: + process.Continue() + + event = lldb.SBEvent() + got_event = process_listener.WaitForEventForBroadcasterWithType(5, broadcaster, lldb.SBProcess.eBroadcastBitStateChanged, event) + event_type = lldb.SBProcess.GetStateFromEvent(event) + self.assertTrue (got_event, "Got an event") + self.assertTrue (event_type == lldb.eStateRunning, "It was the running event.") + + # Now signal the process, and make sure it stops: + process.Signal(signal.SIGUSR1) + + got_event = process_listener.WaitForEventForBroadcasterWithType(5, broadcaster, lldb.SBProcess.eBroadcastBitStateChanged, event) + + event_type = lldb.SBProcess.GetStateFromEvent(event) + self.assertTrue (got_event, "Got an event") + self.assertTrue (event_type == lldb.eStateStopped, "It was the stopped event.") + + # Now make sure the thread was stopped with a SIGUSR1: + threads = lldbutil.get_stopped_threads (process, lldb.eStopReasonSignal) + self.assertTrue (len(threads) == 1, "One thread stopped for a signal.") + thread = threads[0] + self.assertTrue (thread.GetStopReasonDataCount() >= 1, "There was data in the event.") + self.assertTrue (thread.GetStopReasonDataAtIndex(0) == signal.SIGUSR1, "The stop signal was SIGUSR1") if __name__ == '__main__': import atexit |

