JDevlieghere updated this revision to Diff 412479.
JDevlieghere added a comment.
Unsurprisingly no tests failed with the typo. Added a test case to cover
reading from stdin through the `IOHandlerProcessSTDIO`.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D120762/new/
https://reviews.llvm.org/D120762
Files:
lldb/source/Target/Process.cpp
lldb/test/API/iohandler/stdio/Makefile
lldb/test/API/iohandler/stdio/TestIOHandlerProcessSTDIO.py
lldb/test/API/iohandler/stdio/main.cpp
Index: lldb/test/API/iohandler/stdio/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/iohandler/stdio/main.cpp
@@ -0,0 +1,8 @@
+#include <iostream>
+#include <string>
+
+int main(int argc, char **argv) {
+ for (std::string line; std::getline(std::cin, line);)
+ std::cout << "stdout: " << line << '\n';
+ return 0;
+}
Index: lldb/test/API/iohandler/stdio/TestIOHandlerProcessSTDIO.py
===================================================================
--- /dev/null
+++ lldb/test/API/iohandler/stdio/TestIOHandlerProcessSTDIO.py
@@ -0,0 +1,30 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.lldbpexpect import PExpectTest
+
+class TestIOHandlerProcessSTDIO(PExpectTest):
+
+ mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
+
+ # PExpect uses many timeouts internally and doesn't play well
+ # under ASAN on a loaded machine..
+ @skipIfAsan
+ def test(self):
+ self.build()
+ self.launch(executable=self.getBuildArtifact("a.out"), dimensions=(100,500))
+ self.child.sendline("run")
+
+ self.child.send("foo\n")
+ self.child.expect_exact("stdout: foo")
+
+ self.child.send("bar\n")
+ self.child.expect_exact("stdout: bar")
+
+ self.child.send("baz\n")
+ self.child.expect_exact("stdout: baz")
+
+ self.child.sendcontrol('d')
+ self.expect_prompt()
+ self.quit()
Index: lldb/test/API/iohandler/stdio/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/iohandler/stdio/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
Index: lldb/source/Target/Process.cpp
===================================================================
--- lldb/source/Target/Process.cpp
+++ lldb/source/Target/Process.cpp
@@ -4311,6 +4311,12 @@
~IOHandlerProcessSTDIO() override = default;
+ void SetIsRunning(bool running) {
+ std::lock_guard<std::mutex> guard(m_mutex);
+ SetIsDone(!running);
+ m_is_running = running;
+ }
+
// Each IOHandler gets to run until it is done. It should read data from the
// "in" and place output into "out" and "err and return when done.
void Run() override {
@@ -4330,49 +4336,52 @@
// FD_ZERO, FD_SET are not supported on windows
#ifndef _WIN32
const int pipe_read_fd = m_pipe.GetReadFileDescriptor();
- m_is_running = true;
- while (!GetIsDone()) {
+ SetIsRunning(true);
+ while (true) {
+ {
+ std::lock_guard<std::mutex> guard(m_mutex);
+ if (GetIsDone())
+ break;
+ }
+
SelectHelper select_helper;
select_helper.FDSetRead(read_fd);
select_helper.FDSetRead(pipe_read_fd);
Status error = select_helper.Select();
- if (error.Fail()) {
- SetIsDone(true);
- } else {
- char ch = 0;
- size_t n;
- if (select_helper.FDIsSetRead(read_fd)) {
- n = 1;
- if (m_read_file.Read(&ch, n).Success() && n == 1) {
- if (m_write_file.Write(&ch, n).Fail() || n != 1)
- SetIsDone(true);
- } else
- SetIsDone(true);
- }
+ if (error.Fail())
+ break;
+
+ char ch = 0;
+ size_t n;
+ if (select_helper.FDIsSetRead(read_fd)) {
+ n = 1;
+ if (m_read_file.Read(&ch, n).Success() && n == 1) {
+ if (m_write_file.Write(&ch, n).Fail() || n != 1)
+ break;
+ } else
+ break;
+
if (select_helper.FDIsSetRead(pipe_read_fd)) {
size_t bytes_read;
// Consume the interrupt byte
Status error = m_pipe.Read(&ch, 1, bytes_read);
if (error.Success()) {
- switch (ch) {
- case 'q':
- SetIsDone(true);
+ if (ch == 'q')
break;
- case 'i':
+ if (ch == 'i')
if (StateIsRunningState(m_process->GetState()))
m_process->SendAsyncInterrupt();
- break;
- }
}
}
}
}
- m_is_running = false;
+ SetIsRunning(false);
#endif
}
void Cancel() override {
+ std::lock_guard<std::mutex> guard(m_mutex);
SetIsDone(true);
// Only write to our pipe to cancel if we are in
// IOHandlerProcessSTDIO::Run(). We can end up with a python command that
@@ -4429,7 +4438,8 @@
NativeFile m_write_file; // Write to this file (usually the primary pty for
// getting io to debuggee)
Pipe m_pipe;
- std::atomic<bool> m_is_running{false};
+ std::mutex m_mutex;
+ bool m_is_running = false;
};
void Process::SetSTDIOFileDescriptor(int fd) {
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits