From: Walter Erquinigo Date: Tue, 5 Apr 2022 18:21:22 +0000 (-0700) Subject: [lldb-vscode] Implement stderr/stdout on win32 and redirect lldb log to VSCode X-Git-Tag: upstream/15.0.7~11417 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9bcaf6ddfe34943e6ae6a319097524c117908913;p=platform%2Fupstream%2Fllvm.git [lldb-vscode] Implement stderr/stdout on win32 and redirect lldb log to VSCode This patch implements stderr/stdout forwarding on windows. This was previously not implemented in D99974. I added separate callbacks so the output can be sent to the different channels VSCode provides (OutputType::Stdout, OutputType::Stderr, OutputType::Console). This patch also passes a log callback handler to SBDebugger::Create to be able to see logging output when it is enabled. Since the output is now redirect on early startup I removed the calls to SetOutputFileHandle/SetErrorFileHandle, which set them to /dev/null. I send the output of stderr/stdout/lldb log to OutputType::Console Reviewed By: wallace Differential Revision: https://reviews.llvm.org/D123025 --- diff --git a/lldb/tools/lldb-vscode/OutputRedirector.cpp b/lldb/tools/lldb-vscode/OutputRedirector.cpp index 7432a828d045..9243915f7d78 100644 --- a/lldb/tools/lldb-vscode/OutputRedirector.cpp +++ b/lldb/tools/lldb-vscode/OutputRedirector.cpp @@ -6,20 +6,27 @@ // //===----------------------------------------------------------------------===/ -#if !defined(_WIN32) +#if defined(_WIN32) +#include +#include +#else #include #endif #include "OutputRedirector.h" +#include "llvm/ADT/StringRef.h" using namespace llvm; namespace lldb_vscode { Error RedirectFd(int fd, std::function callback) { -#if !defined(_WIN32) int new_fd[2]; +#if defined(_WIN32) + if (_pipe(new_fd, 4096, O_TEXT) == -1) { +#else if (pipe(new_fd) == -1) { +#endif int error = errno; return createStringError(inconvertibleErrorCode(), "Couldn't create new pipe for fd %d. %s", fd, @@ -45,11 +52,10 @@ Error RedirectFd(int fd, std::function callback) { continue; break; } - callback(StringRef(buffer, bytes_count).str()); + callback(StringRef(buffer, bytes_count)); } }); t.detach(); -#endif return Error::success(); } diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp index 83a9762df604..869c125ec034 100644 --- a/lldb/tools/lldb-vscode/lldb-vscode.cpp +++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -65,11 +65,6 @@ #define PATH_MAX MAX_PATH #endif typedef int socklen_t; -constexpr const char *dev_null_path = "nul"; - -#else -constexpr const char *dev_null_path = "/dev/null"; - #endif using namespace lldb_vscode; @@ -1446,23 +1441,13 @@ void request_modules(const llvm::json::Object &request) { // }] // } void request_initialize(const llvm::json::Object &request) { - g_vsc.debugger = lldb::SBDebugger::Create(true /*source_init_files*/); + auto log_cb = [](const char *buf, void *baton) -> void { + g_vsc.SendOutput(OutputType::Console, llvm::StringRef{buf}); + }; + g_vsc.debugger = + lldb::SBDebugger::Create(true /*source_init_files*/, log_cb, nullptr); g_vsc.progress_event_thread = std::thread(ProgressEventThreadFunction); - // Create an empty target right away since we might get breakpoint requests - // 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. - 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 - // 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. - g_vsc.debugger.SetOutputFileHandle(out, true); - 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); @@ -3147,18 +3132,25 @@ void redirection_test() { /// \return /// A fd pointing to the original stdout. int SetupStdoutStderrRedirection() { - int new_stdout_fd = dup(fileno(stdout)); - auto stdout_err_redirector_callback = [&](llvm::StringRef data) { - g_vsc.SendOutput(OutputType::Console, data); + int stdoutfd = fileno(stdout); + int new_stdout_fd = dup(stdoutfd); + auto output_callback_stderr = [](llvm::StringRef data) { + g_vsc.SendOutput(OutputType::Stderr, data); }; - - for (int fd : {fileno(stdout), fileno(stderr)}) { - if (llvm::Error err = RedirectFd(fd, stdout_err_redirector_callback)) { - std::string error_message = llvm::toString(std::move(err)); - if (g_vsc.log) - *g_vsc.log << error_message << std::endl; - stdout_err_redirector_callback(error_message); - } + auto output_callback_stdout = [](llvm::StringRef data) { + g_vsc.SendOutput(OutputType::Stdout, data); + }; + if (llvm::Error err = RedirectFd(stdoutfd, output_callback_stdout)) { + std::string error_message = llvm::toString(std::move(err)); + if (g_vsc.log) + *g_vsc.log << error_message << std::endl; + output_callback_stderr(error_message); + } + if (llvm::Error err = RedirectFd(fileno(stderr), output_callback_stderr)) { + std::string error_message = llvm::toString(std::move(err)); + if (g_vsc.log) + *g_vsc.log << error_message << std::endl; + output_callback_stderr(error_message); } /// used only by TestVSCode_redirection_to_console.py