1 //===-- OutputRedirector.cpp -----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===/
8 
9 #if !defined(_WIN32)
10 #include <unistd.h>
11 #endif
12 
13 #include "OutputRedirector.h"
14 
15 using namespace llvm;
16 
17 namespace lldb_vscode {
18 
19 Error RedirectFd(int fd, std::function<void(llvm::StringRef)> callback) {
20 #if !defined(_WIN32)
21   int new_fd[2];
22   if (pipe(new_fd) == -1) {
23     int error = errno;
24     return createStringError(inconvertibleErrorCode(),
25                              "Couldn't create new pipe for fd %d. %s", fd,
26                              strerror(error));
27   }
28 
29   if (dup2(new_fd[1], fd) == -1) {
30     int error = errno;
31     return createStringError(inconvertibleErrorCode(),
32                              "Couldn't override the fd %d. %s", fd,
33                              strerror(error));
34   }
35 
36   int read_fd = new_fd[0];
37   std::thread t([read_fd, callback]() {
38     char buffer[4096];
39     while (true) {
40       ssize_t bytes_count = read(read_fd, &buffer, sizeof(buffer));
41       if (bytes_count == 0)
42         return;
43       if (bytes_count == -1) {
44         if (errno == EAGAIN || errno == EINTR)
45           continue;
46         break;
47       }
48       callback(StringRef(buffer, bytes_count).str());
49     }
50   });
51   t.detach();
52 #endif
53   return Error::success();
54 }
55 
56 } // namespace lldb_vscode
57