aadsm updated this revision to Diff 276894.
aadsm added a comment.

This update still doesn't add windows support but I just want to get a feel 
that I'm going on the right direction.
It addresses the following:

- redirect stdout/err as early as possible to avoid something writing to it, 
and only starts or ends redirection it once it's safe.
- adds a mutex to OutputStream::write_full to make sure multiple threads don't 
try to write to the output fd at the same time.

> We should also think about testing all of this. Do we have a reliable 
> mechanism to produce stdout/err output from lldb?

this turned out to be harder than I thought it would be, my plan was to print 
to stdout in python from a thread but I never see that print anywhere (not sure 
why though). A sure way to test this (what I did manually) is to put a `script 
print('foo')` command in lldninit. Unfortunately I can't use a local lldbinit 
since that's a concept of the lldb binary and not of liblldb (unless we want to 
add that option to lldb-vscode as well), so not really sure about this as well.
I also tried to use a `breakpoint command add -o 'script print("foo")'` but 
same behaviour, I never saw that print. Still don't know how to tackle this, 
need to think more about it.

> Or, if this output is going to the same place as the SBDebuggers notion of 
> stdout/err,

There no guarantee of this, people can just use sys.stdout.write in python.

> given that Richard has found some vscode code which already tries to send 
> stderr to the console window

I would still prefer to wrap liblldb's stderr into a console message so people 
can see it in the client(e.g.: VSCode) console rather than outputting it 
through the lldb-vscode stderr which will then be up to the client to decide 
what to do with it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80659/new/

https://reviews.llvm.org/D80659

Files:
  lldb/tools/lldb-vscode/IOStream.cpp
  lldb/tools/lldb-vscode/IOStream.h
  lldb/tools/lldb-vscode/lldb-vscode.cpp

Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===================================================================
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -486,6 +486,43 @@
   }
 }
 
+class FileDescriptorToConsoleOutputRedirector {
+  private:
+    int m_captured_fd[2];
+    std::thread m_thread;
+
+  public:
+    FileDescriptorToConsoleOutputRedirector(int fd) {
+      pipe(m_captured_fd);
+      dup2(m_captured_fd[1], fd);
+    };
+    ~FileDescriptorToConsoleOutputRedirector() {
+      StopRedirecting();
+    }
+    // Only call this once.
+    void StartRedirecting() {
+      int read_fd = m_captured_fd[0];
+
+      m_thread = std::thread([read_fd] {
+        char buffer[4096];
+        while (true) {
+          ssize_t bytes_count = read(read_fd, &buffer, sizeof(buffer));
+          if (bytes_count == 0)
+            return;
+          g_vsc.SendOutput(OutputType::Console, buffer);
+        }
+      });
+      m_thread.detach();
+    }
+
+    void StopRedirecting() {
+      if (!m_thread.joinable())
+        return;
+      close(m_captured_fd[1]);
+      m_thread.join();
+    }
+};
+
 // "AttachRequest": {
 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
 //     "type": "object",
@@ -2781,7 +2818,9 @@
 }
 
 int main(int argc, char *argv[]) {
-
+  int stdout_fd = dup(fileno(stdout));
+  FileDescriptorToConsoleOutputRedirector stdout_redirector(fileno(stdout));
+  FileDescriptorToConsoleOutputRedirector stderr_redirector(fileno(stderr));
   // Initialize LLDB first before we do anything.
   lldb::SBDebugger::Initialize();
 
@@ -2824,9 +2863,11 @@
     }
   } else {
     g_vsc.input.descriptor = StreamDescriptor::from_file(fileno(stdin), false);
-    g_vsc.output.descriptor =
-        StreamDescriptor::from_file(fileno(stdout), false);
+    g_vsc.output.descriptor = StreamDescriptor::from_file(stdout_fd, false);
   }
+  // Can start redirecting now that the output description has been properly set.
+  stdout_redirector.StartRedirecting();
+  stderr_redirector.StartRedirecting();
   auto request_handlers = GetRequestHandlers();
   uint32_t packet_idx = 0;
   while (!g_vsc.sent_terminated_event) {
@@ -2875,5 +2916,9 @@
   // We must terminate the debugger in a thread before the C++ destructor
   // chain messes everything up.
   lldb::SBDebugger::Terminate();
+  // Can now safely stop redirecting since lldb will no longer emit stdout
+  // or stderr messages.
+  stdout_redirector.StopRedirecting();
+  stderr_redirector.StopRedirecting();
   return 0;
 }
Index: lldb/tools/lldb-vscode/IOStream.h
===================================================================
--- lldb/tools/lldb-vscode/IOStream.h
+++ lldb/tools/lldb-vscode/IOStream.h
@@ -63,6 +63,9 @@
   StreamDescriptor descriptor;
 
   bool write_full(llvm::StringRef str);
+
+  private:
+  std::mutex m_mutex;
 };
 } // namespace lldb_vscode
 
Index: lldb/tools/lldb-vscode/IOStream.cpp
===================================================================
--- lldb/tools/lldb-vscode/IOStream.cpp
+++ lldb/tools/lldb-vscode/IOStream.cpp
@@ -70,6 +70,7 @@
 }
 
 bool OutputStream::write_full(llvm::StringRef str) {
+  std::lock_guard<std::mutex> lock(m_mutex);
   while (!str.empty()) {
     int bytes_written = 0;
     if (descriptor.m_is_socket)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to