--- /dev/null
+"""
+Test completion in our IOHandlers.
+"""
+
+import os
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.lldbpexpect import PExpectTest
+
+
+class BreakpointCallbackCommandSource(PExpectTest):
+
+ mydir = TestBase.compute_mydir(__file__)
+ file_to_source = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'source.lldb')
+
+ # PExpect uses many timeouts internally and doesn't play well
+ # under ASAN on a loaded machine..
+ @skipIfAsan
+ @skipIfEditlineSupportMissing
+ def test_breakpoint_callback_command_source(self):
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+
+ self.launch(exe)
+ self.expect("b main", substrs=["Breakpoint 1"])
+ self.child.send("breakpoint command add -s python\n")
+ self.child.send(
+ "frame.GetThread().GetProcess().GetTarget().GetDebugger().HandleCommand('command source -s true {}')\n"
+ .format(self.file_to_source))
+ self.child.send("DONE\n")
+ self.expect_prompt()
+ self.expect("run", substrs=["Process", "stopped"])
+ self.expect("script print(foo)", substrs=["95126"])
}
void Debugger::RunIOHandlers() {
+ IOHandlerSP reader_sp = m_io_handler_stack.Top();
while (true) {
- IOHandlerSP reader_sp(m_io_handler_stack.Top());
if (!reader_sp)
break;
reader_sp->Run();
+ {
+ std::lock_guard<std::recursive_mutex> guard(
+ m_io_handler_synchronous_mutex);
+
+ // Remove all input readers that are done from the top of the stack
+ while (true) {
+ IOHandlerSP top_reader_sp = m_io_handler_stack.Top();
+ if (top_reader_sp && top_reader_sp->GetIsDone())
+ PopIOHandler(top_reader_sp);
+ else
+ break;
+ }
+ reader_sp = m_io_handler_stack.Top();
+ }
+ }
+ ClearIOHandlers();
+}
+
+void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) {
+ std::lock_guard<std::recursive_mutex> guard(m_io_handler_synchronous_mutex);
+
+ PushIOHandler(reader_sp);
+ IOHandlerSP top_reader_sp = reader_sp;
- // Remove all input readers that are done from the top of the stack
+ while (top_reader_sp) {
+ if (!top_reader_sp)
+ break;
+
+ top_reader_sp->Run();
+
+ // Don't unwind past the starting point.
+ if (top_reader_sp.get() == reader_sp.get()) {
+ if (PopIOHandler(reader_sp))
+ break;
+ }
+
+ // If we pushed new IO handlers, pop them if they're done or restart the
+ // loop to run them if they're not.
while (true) {
- IOHandlerSP top_reader_sp = m_io_handler_stack.Top();
- if (top_reader_sp && top_reader_sp->GetIsDone())
+ top_reader_sp = m_io_handler_stack.Top();
+ if (top_reader_sp && top_reader_sp->GetIsDone()) {
PopIOHandler(top_reader_sp);
- else
+ // Don't unwind past the starting point.
+ if (top_reader_sp.get() == reader_sp.get())
+ return;
+ } else {
break;
+ }
}
}
- ClearIOHandlers();
}
bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
PushIOHandler(reader_sp, cancel_top_handler);
}
-void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) {
- PushIOHandler(reader_sp);
-
- IOHandlerSP top_reader_sp = reader_sp;
- while (top_reader_sp) {
- top_reader_sp->Run();
-
- if (top_reader_sp.get() == reader_sp.get()) {
- if (PopIOHandler(reader_sp))
- break;
- }
-
- while (true) {
- top_reader_sp = m_io_handler_stack.Top();
- if (top_reader_sp && top_reader_sp->GetIsDone())
- PopIOHandler(top_reader_sp);
- else
- break;
- }
- }
-}
-
void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out,
StreamFileSP &err) {
// Before an IOHandler runs, it must have in/out/err streams. This function