Enable capturing stdout/stderr of launched application
authorIgor Kulaychuk <i.kulaychuk@samsung.com>
Fri, 25 May 2018 19:28:01 +0000 (22:28 +0300)
committerIgor Kulaychuk <i.kulaychuk@samsung.com>
Tue, 5 Jun 2018 15:08:23 +0000 (18:08 +0300)
src/debug/netcoredbg/main.cpp
src/debug/netcoredbg/platform.cpp
src/debug/netcoredbg/platform.h

index 620a4eb..968402c 100644 (file)
@@ -135,7 +135,6 @@ int main(int argc, char *argv[])
         }
     }
 
-    IORedirectServer server(serverPort);
     ManagedDebugger debugger;
     std::unique_ptr<Protocol> 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();
index 793647a..375e646 100644 (file)
@@ -7,6 +7,7 @@
 #include <cstring>
 #include <set>
 #include <fstream>
+#include <thread>
 
 #include <dirent.h>
 #include <sys/stat.h>
@@ -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<void(std::string)> onStdOut,
+    std::function<void(std::string)> 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<void()> GetFdReadFunction(int fd, std::function<void(std::string)> 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<void(std::string)> onStdOut,
+                                      std::function<void(std::string)> 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();
+}
index 5f5ac0b..336f6f4 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <string>
 #include <iostream>
+#include <functional>
 
 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<void(std::string)> onStdOut,
+        std::function<void(std::string)> onStdErr);
 public:
-    IORedirectServer(uint16_t port);
+    IORedirectServer(
+        uint16_t port,
+        std::function<void(std::string)> onStdOut,
+        std::function<void(std::string)> onStdErr);
     ~IORedirectServer();
     operator bool() const { return m_sockfd != -1; }
 };