summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Target/Process.h5
-rw-r--r--lldb/source/Target/ExecutionContext.cpp6
-rw-r--r--lldb/source/Target/Process.cpp3
-rw-r--r--lldb/test/functionalities/signal/TestSendSignal.py96
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
OpenPOWER on IntegriCloud