forked from OSchip/llvm-project
[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
This commit is contained in:
parent
5561ab3495
commit
9bcaf6ddfe
|
@ -6,20 +6,27 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===/
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "OutputRedirector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace lldb_vscode {
|
||||
|
||||
Error RedirectFd(int fd, std::function<void(llvm::StringRef)> 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<void(llvm::StringRef)> callback) {
|
|||
continue;
|
||||
break;
|
||||
}
|
||||
callback(StringRef(buffer, bytes_count).str());
|
||||
callback(StringRef(buffer, bytes_count));
|
||||
}
|
||||
});
|
||||
t.detach();
|
||||
#endif
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue