6
6
//
7
7
// ===----------------------------------------------------------------------===/
8
8
9
+ #include " OutputRedirector.h"
10
+ #include " DAP.h"
11
+ #include " llvm/ADT/StringRef.h"
9
12
#include " llvm/Support/Error.h"
10
13
#include < system_error>
11
14
#if defined(_WIN32)
15
18
#include < unistd.h>
16
19
#endif
17
20
18
- #include " DAP.h"
19
- #include " OutputRedirector.h"
20
- #include " llvm/ADT/StringRef.h"
21
-
22
21
using lldb_private::Pipe;
23
- using lldb_private::Status;
24
22
using llvm::createStringError;
25
23
using llvm::Error;
26
24
using llvm::Expected;
25
+ using llvm::inconvertibleErrorCode;
27
26
using llvm::StringRef;
28
27
29
28
namespace lldb_dap {
30
29
30
+ int OutputRedirector::kInvalidDescriptor = -1 ;
31
+
32
+ OutputRedirector::OutputRedirector () : m_fd(kInvalidDescriptor ) {}
33
+
31
34
Expected<int > OutputRedirector::GetWriteFileDescriptor () {
32
- if (!m_pipe. CanWrite () )
35
+ if (m_fd == kInvalidDescriptor )
33
36
return createStringError (std::errc::bad_file_descriptor,
34
37
" write handle is not open for writing" );
35
- return m_pipe. GetWriteFileDescriptor () ;
38
+ return m_fd ;
36
39
}
37
40
38
41
Error 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 ];
42
44
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
+ }
50
54
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 ;
53
68
break ;
69
+ }
54
70
55
- callback (StringRef (buffer, bytes_read ));
71
+ callback (StringRef (buffer, bytes_count ));
56
72
}
73
+ ::close (read_fd);
57
74
});
58
75
59
76
return Error::success ();
@@ -62,14 +79,15 @@ Error OutputRedirector::RedirectTo(std::function<void(StringRef)> callback) {
62
79
void OutputRedirector::Stop () {
63
80
m_stopped = true ;
64
81
65
- if (m_pipe.CanWrite ()) {
82
+ if (m_fd != kInvalidDescriptor ) {
83
+ int fd = m_fd;
84
+ m_fd = kInvalidDescriptor ;
66
85
// Closing the pipe may not be sufficient to wake up the thread in case the
67
86
// write descriptor is duplicated (to stdout/err or to another process).
68
87
// Write a null byte to ensure the read call returns.
69
88
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);
73
91
m_forwarder.join ();
74
92
}
75
93
}
0 commit comments