66//
77// ===----------------------------------------------------------------------===/
88
9+ #include " OutputRedirector.h"
10+ #include " DAP.h"
11+ #include " llvm/ADT/StringRef.h"
912#include " llvm/Support/Error.h"
1013#include < system_error>
1114#if defined(_WIN32)
1518#include < unistd.h>
1619#endif
1720
18- #include " DAP.h"
19- #include " OutputRedirector.h"
20- #include " llvm/ADT/StringRef.h"
21-
2221using lldb_private::Pipe;
23- using lldb_private::Status;
2422using llvm::createStringError;
2523using llvm::Error;
2624using llvm::Expected;
25+ using llvm::inconvertibleErrorCode;
2726using llvm::StringRef;
2827
2928namespace lldb_dap {
3029
30+ int OutputRedirector::kInvalidDescriptor = -1 ;
31+
32+ OutputRedirector::OutputRedirector () : m_fd(kInvalidDescriptor ) {}
33+
3134Expected<int > OutputRedirector::GetWriteFileDescriptor () {
32- if (!m_pipe. CanWrite () )
35+ if (m_fd == kInvalidDescriptor )
3336 return createStringError (std::errc::bad_file_descriptor,
3437 " write handle is not open for writing" );
35- return m_pipe. GetWriteFileDescriptor () ;
38+ return m_fd ;
3639}
3740
3841Error OutputRedirector::RedirectTo (std::function<void (StringRef)> callback) {
39- Status status = m_pipe.CreateNew (/* child_process_inherit=*/ false );
40- if (status.Fail ())
41- return status.takeError ();
42+ assert (m_fd == kInvalidDescriptor && " Output readirector already started." );
43+ int new_fd[2 ];
4244
43- m_forwarder = std::thread ([this , callback]() {
44- char buffer[OutputBufferSize];
45- while (m_pipe.CanRead () && !m_stopped) {
46- size_t bytes_read;
47- Status status = m_pipe.Read (&buffer, sizeof (buffer), bytes_read);
48- if (status.Fail ())
49- continue ;
45+ #if defined(_WIN32)
46+ if (::_pipe (new_fd, OutputBufferSize, O_TEXT) == -1 ) {
47+ #else
48+ if (::pipe (new_fd) == -1 ) {
49+ #endif
50+ int error = errno;
51+ return createStringError (inconvertibleErrorCode (),
52+ " Couldn't create new pipe %s" , strerror (error));
53+ }
5054
51- // EOF detected
52- if (bytes_read == 0 || m_stopped)
55+ int read_fd = new_fd[0 ];
56+ m_fd = new_fd[1 ];
57+ m_forwarder = std::thread ([this , callback, read_fd]() {
58+ char buffer[OutputBufferSize];
59+ while (!m_stopped) {
60+ ssize_t bytes_count = ::read (read_fd, &buffer, sizeof (buffer));
61+ // EOF detected.
62+ if (bytes_count == 0 )
63+ break ;
64+ if (bytes_count == -1 ) {
65+ // Skip non-fatal errors.
66+ if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)
67+ continue ;
5368 break ;
69+ }
5470
55- callback (StringRef (buffer, bytes_read ));
71+ callback (StringRef (buffer, bytes_count ));
5672 }
73+ ::close (read_fd);
5774 });
5875
5976 return Error::success ();
@@ -62,14 +79,15 @@ Error OutputRedirector::RedirectTo(std::function<void(StringRef)> callback) {
6279void OutputRedirector::Stop () {
6380 m_stopped = true ;
6481
65- if (m_pipe.CanWrite ()) {
82+ if (m_fd != kInvalidDescriptor ) {
83+ int fd = m_fd;
84+ m_fd = kInvalidDescriptor ;
6685 // Closing the pipe may not be sufficient to wake up the thread in case the
6786 // write descriptor is duplicated (to stdout/err or to another process).
6887 // Write a null byte to ensure the read call returns.
6988 char buf[] = " \0 " ;
70- size_t bytes_written;
71- m_pipe.Write (buf, sizeof (buf), bytes_written);
72- m_pipe.CloseWriteFileDescriptor ();
89+ ::write (fd, buf, sizeof (buf));
90+ ::close (fd);
7391 m_forwarder.join ();
7492 }
7593}
0 commit comments