lanza created this revision.
lanza requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

Just uploading this incase I want to look at it again at some point in the 
future.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D114491

Files:
  lldb/tools/lldb-vscode/VSCode.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
@@ -16,6 +16,7 @@
 #include <cstring>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <termios.h>
 #if defined(_WIN32)
 // We need to #define NOMINMAX in order to skip `min()` and `max()` macro
 // definitions that conflict with other system headers.
@@ -552,6 +553,34 @@
   }
 }
 
+static void reset_stdin_termios();
+static bool g_old_stdin_termios_is_valid = false;
+static struct termios g_old_stdin_termios;
+
+// In the Driver::MainLoop, we change the terminal settings.  This function is
+// added as an atexit handler to make sure we clean them up.
+static void reset_stdin_termios() {
+  if (g_old_stdin_termios_is_valid) {
+    g_old_stdin_termios_is_valid = false;
+    ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
+  }
+}
+
+void CommandInterpreterThreadFunction() {
+  if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) {
+    g_old_stdin_termios_is_valid = true;
+    atexit(reset_stdin_termios);
+  }
+#ifndef _MSC_VER
+  // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets
+  // which causes it to miss newlines depending on whether there have been an
+  // odd or even number of characters.  Bug has been reported to MS via Connect.
+ ::setbuf(stdin, nullptr);
+#endif
+  ::setbuf(stdout, nullptr);
+  g_vsc.debugger.RunCommandInterpreter(false, false);
+}
+
 // "AttachRequest": {
 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
 //     "type": "object",
@@ -878,6 +907,9 @@
     g_vsc.broadcaster.BroadcastEventByType(eBroadcastBitStopProgressThread);
     g_vsc.progress_event_thread.join();
   }
+
+  if (g_vsc.command_interpreter_thread.joinable())
+    g_vsc.event_thread.join();
 }
 
 void request_exceptionInfo(const llvm::json::Object &request) {
@@ -1415,6 +1447,11 @@
 //     "supportsRunInTerminalRequest": {
 //       "type": "boolean",
 //       "description": "Client supports the runInTerminal request."
+//     },
+//     "supportsCommandInterpreter": {
+//       "type": "boolean",
+//       "description": "Client launches lldb-vscode in a terminal and thus
+//                       supports attaching the CommandInterpreter."
 //     }
 //   },
 //   "required": [ "adapterID" ]
@@ -1439,6 +1476,38 @@
   // before we are given an executable to launch in a "launch" request, or a
   // executable when attaching to a process by process ID in a "attach"
   // request.
+  //
+  // Start our event thread so we can receive events from the debugger, target,
+  // process and more.
+  g_vsc.event_thread = std::thread(EventThreadFunction);
+
+    // Set the output and error file handles to redirect into nothing iff the
+  // input and output are set to stdin and stdout. If we are receiving DAP
+  // packets over a socket then keep them up. Otherwise if any code in LLDB
+  // prints to the debugger file handles, the output and error file handles are
+  // initialized to STDOUT and STDERR and any output will kill our debug
+  // session.
+  if (!g_vsc.input.descriptor.m_is_socket) {
+    FILE *out = llvm::sys::RetryAfterSignal(nullptr, fopen, dev_null_path, "w");
+    if (out) {
+      g_vsc.debugger.SetOutputFileHandle(out, true);
+      g_vsc.debugger.SetErrorFileHandle(out, false);
+    }
+  }
+
+  // We can't attach the command interpreter if the DAP packets are being sent
+  // via stdin/stdout. We would require extra sockets. So only attach the CI iff
+  // we are communicating via a socket.
+  if (g_vsc.input.descriptor.m_is_socket) {
+    auto arguments = request.getObject("arguments");
+    auto supports_ci =
+        GetBoolean(arguments, "supportsCommandInterpreter", false);
+    if (supports_ci) {
+      g_vsc.command_interpreter_thread =
+          std::thread(CommandInterpreterThreadFunction);
+    }
+  }
+
   FILE *out = llvm::sys::RetryAfterSignal(nullptr, fopen, dev_null_path, "w");
   if (out) {
     // Set the output and error file handles to redirect into nothing otherwise
@@ -1449,9 +1518,6 @@
     g_vsc.debugger.SetErrorFileHandle(out, false);
   }
 
-  // Start our event thread so we can receive events from the debugger, target,
-  // process and more.
-  g_vsc.event_thread = std::thread(EventThreadFunction);
 
   llvm::json::Object response;
   FillResponse(request, response);
Index: lldb/tools/lldb-vscode/VSCode.h
===================================================================
--- lldb/tools/lldb-vscode/VSCode.h
+++ lldb/tools/lldb-vscode/VSCode.h
@@ -130,6 +130,7 @@
   lldb::SBBroadcaster broadcaster;
   std::thread event_thread;
   std::thread progress_event_thread;
+  std::thread command_interpreter_thread;
   std::unique_ptr<std::ofstream> log;
   llvm::DenseMap<lldb::addr_t, int64_t> addr_to_source_ref;
   llvm::DenseMap<int64_t, SourceReference> source_map;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to