From ee048f392c798992b5d21450471a29c54e0817fc Mon Sep 17 00:00:00 2001 From: Igor Kulaychuk Date: Fri, 25 May 2018 22:28:01 +0300 Subject: [PATCH] Enable capturing stdout/stderr of launched application --- src/debug/netcoredbg/main.cpp | 7 +++- src/debug/netcoredbg/platform.cpp | 78 +++++++++++++++++++++++++++++++++++++-- src/debug/netcoredbg/platform.h | 13 ++++++- 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/debug/netcoredbg/main.cpp b/src/debug/netcoredbg/main.cpp index 620a4eb..968402c 100644 --- a/src/debug/netcoredbg/main.cpp +++ b/src/debug/netcoredbg/main.cpp @@ -135,7 +135,6 @@ int main(int argc, char *argv[]) } } - IORedirectServer server(serverPort); ManagedDebugger debugger; std::unique_ptr protocol; @@ -170,6 +169,12 @@ int main(int argc, char *argv[]) debugger.SetProtocol(protocol.get()); + IORedirectServer server( + serverPort, + [&protocol](std::string text) { protocol->EmitOutputEvent(OutputEvent(OutputStdOut, text)); }, + [&protocol](std::string text) { protocol->EmitOutputEvent(OutputEvent(OutputStdErr, text)); } + ); + if (pidDebuggee != 0) { debugger.Initialize(); diff --git a/src/debug/netcoredbg/platform.cpp b/src/debug/netcoredbg/platform.cpp index 793647a..375e646 100644 --- a/src/debug/netcoredbg/platform.cpp +++ b/src/debug/netcoredbg/platform.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -280,8 +281,20 @@ int fdbuf::underflow() : traits_type::to_int_type(*this->gptr()); } -IORedirectServer::IORedirectServer(uint16_t port) : m_in(nullptr), m_out(nullptr), m_sockfd(-1) +IORedirectServer::IORedirectServer( + uint16_t port, + std::function onStdOut, + std::function onStdErr) : + m_in(nullptr), + m_out(nullptr), + m_sockfd(-1), + m_realStdInFd(STDIN_FILENO), + m_realStdOutFd(STDOUT_FILENO), + m_realStdErrFd(STDERR_FILENO), + m_appStdIn(-1) { + RedirectOutput(onStdOut, onStdErr); + int newsockfd; socklen_t clilen; struct sockaddr_in serv_addr, cli_addr; @@ -319,9 +332,12 @@ IORedirectServer::IORedirectServer(uint16_t port) : m_in(nullptr), m_out(nullptr ::listen(m_sockfd, 5); - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); + close(m_realStdInFd); + close(m_realStdOutFd); + close(m_realStdErrFd); + m_realStdInFd = -1; + m_realStdOutFd = -1; + m_realStdErrFd = -1; clilen = sizeof(cli_addr); newsockfd = ::accept(m_sockfd, (struct sockaddr *) &cli_addr, &clilen); @@ -347,3 +363,57 @@ IORedirectServer::~IORedirectServer() delete m_out; ::close(m_sockfd); } + +static std::function GetFdReadFunction(int fd, std::function cb) +{ + return [fd, cb]() { + char buffer[PIPE_BUF]; + + while (true) + { + //Read up to PIPE_BUF bytes of what's currently at the stdin + ssize_t read_size = read(fd, buffer, PIPE_BUF); + if (read_size <= 0) + { + if (errno == EINTR) + continue; + break; + } + cb(std::string(buffer, read_size)); + } + }; +} + +void IORedirectServer::RedirectOutput(std::function onStdOut, + std::function onStdErr) +{ + // TODO: fcntl(fd, F_SETFD, FD_CLOEXEC); + m_realStdInFd = dup(STDIN_FILENO); + m_realStdOutFd = dup(STDOUT_FILENO); + m_realStdErrFd = dup(STDERR_FILENO); + + std::cin.rdbuf(new fdbuf(m_realStdInFd)); + std::cout.rdbuf(new fdbuf(m_realStdOutFd)); + std::cerr.rdbuf(new fdbuf(m_realStdErrFd)); + + int inPipe[2]; + int outPipe[2]; + int errPipe[2]; + + if (pipe(inPipe) == -1) return; + if (pipe(outPipe) == -1) return; + if (pipe(errPipe) == -1) return; + + if (dup2(inPipe[0], STDIN_FILENO) == -1) return; + if (dup2(outPipe[1], STDOUT_FILENO) == -1) return; + if (dup2(errPipe[1], STDERR_FILENO) == -1) return; + + close(inPipe[0]); + close(outPipe[1]); + close(errPipe[1]); + + m_appStdIn = inPipe[1]; + + std::thread(GetFdReadFunction(outPipe[0], onStdOut)).detach(); + std::thread(GetFdReadFunction(errPipe[0], onStdErr)).detach(); +} diff --git a/src/debug/netcoredbg/platform.h b/src/debug/netcoredbg/platform.h index 5f5ac0b..336f6f4 100644 --- a/src/debug/netcoredbg/platform.h +++ b/src/debug/netcoredbg/platform.h @@ -5,6 +5,7 @@ #include #include +#include unsigned long OSPageSize(); void AddFilesFromDirectoryToTpaList(const std::string &directory, std::string &tpaList); @@ -23,8 +24,18 @@ class IORedirectServer std::streambuf *m_prevIn; std::streambuf *m_prevOut; int m_sockfd; + int m_realStdInFd; + int m_realStdOutFd; + int m_realStdErrFd; + int m_appStdIn; + void RedirectOutput( + std::function onStdOut, + std::function onStdErr); public: - IORedirectServer(uint16_t port); + IORedirectServer( + uint16_t port, + std::function onStdOut, + std::function onStdErr); ~IORedirectServer(); operator bool() const { return m_sockfd != -1; } }; -- 2.7.4