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 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