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