xref: /openbsd-src/gnu/llvm/lldb/tools/lldb-vscode/OutputRedirector.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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 <fcntl.h>
11 #include <io.h>
12 #else
13 #include <unistd.h>
14 #endif
15 
16 #include "OutputRedirector.h"
17 #include "llvm/ADT/StringRef.h"
18 
19 using namespace llvm;
20 
21 namespace lldb_vscode {
22 
RedirectFd(int fd,std::function<void (llvm::StringRef)> callback)23 Error RedirectFd(int fd, std::function<void(llvm::StringRef)> callback) {
24   int new_fd[2];
25 #if defined(_WIN32)
26   if (_pipe(new_fd, 4096, O_TEXT) == -1) {
27 #else
28   if (pipe(new_fd) == -1) {
29 #endif
30     int error = errno;
31     return createStringError(inconvertibleErrorCode(),
32                              "Couldn't create new pipe for fd %d. %s", fd,
33                              strerror(error));
34   }
35 
36   if (dup2(new_fd[1], fd) == -1) {
37     int error = errno;
38     return createStringError(inconvertibleErrorCode(),
39                              "Couldn't override the fd %d. %s", fd,
40                              strerror(error));
41   }
42 
43   int read_fd = new_fd[0];
44   std::thread t([read_fd, callback]() {
45     char buffer[4096];
46     while (true) {
47       ssize_t bytes_count = read(read_fd, &buffer, sizeof(buffer));
48       if (bytes_count == 0)
49         return;
50       if (bytes_count == -1) {
51         if (errno == EAGAIN || errno == EINTR)
52           continue;
53         break;
54       }
55       callback(StringRef(buffer, bytes_count));
56     }
57   });
58   t.detach();
59   return Error::success();
60 }
61 
62 } // namespace lldb_vscode
63