LLDB mainline
PseudoConsole.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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#ifndef LIBLLDB_HOST_WINDOWS_PSEUDOCONSOLE_H_
10#define LIBLLDB_HOST_WINDOWS_PSEUDOCONSOLE_H_
11
12#include "llvm/Support/Error.h"
13#include <atomic>
14#include <condition_variable>
15#include <mutex>
16#include <string>
17
18#define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x20016
19typedef void *HANDLE;
20typedef void *HPCON;
21
22namespace lldb_private {
23
25
26public:
27 enum class Mode { ConPTY, Pipe, None };
28
29 PseudoConsole() = default;
31
32 PseudoConsole(const PseudoConsole &) = delete;
36
37 /// Creates a named pipe pair for overlapped I/O. The read end is set to
38 /// non-blocking (PIPE_NOWAIT).
39 /// On failure any handles that were successfully opened are closed and an
40 /// error is returned.
41 llvm::Error CreateOverlappedPipePair(HANDLE &out_read, HANDLE &out_write,
42 bool inheritable);
43
44 /// Creates and opens a new ConPTY instance with a default console size of
45 /// 80x25. Also sets up the associated STDIN/STDOUT pipes and drains any
46 /// initialization sequences emitted by Windows.
47 ///
48 /// \return
49 /// An llvm::Error if the ConPTY could not be created, or if ConPTY is
50 /// not available on this version of Windows, llvm::Error::success()
51 /// otherwise.
52 llvm::Error OpenPseudoConsole();
53
54 /// Creates a pair of anonymous pipes to use for stdio instead of a ConPTY.
55 ///
56 /// \return
57 /// An llvm::Error if the pipes could not be created.
58 llvm::Error OpenAnonymousPipes();
59
60 /// Closes the ConPTY and invalidates its handle, without closing the STDIN
61 /// and STDOUT pipes. Closing the ConPTY signals EOF to any process currently
62 /// attached to it.
63 void Close();
64
65 /// Closes the STDIN and STDOUT pipe handles and invalidates them.
67
68 /// Closes the child-side pipe handles (stdin read end and stdout/stderr write
69 /// end) that were passed to CreateProcessW. Must be called after a successful
70 /// CreateProcessW to avoid keeping the pipes alive indefinitely.
72
73 /// Returns whether the ConPTY and its pipes are currently open and valid.
74 bool IsConnected() const;
75
76 /// The ConPTY HPCON handle accessor.
77 ///
78 /// This object retains ownership of the HPCON when this accessor is used.
79 ///
80 /// \return
81 /// The ConPTY HPCON handle, or INVALID_HANDLE_VALUE if it is currently
82 /// invalid.
84
85 /// The STDOUT read HANDLE accessor.
86 ///
87 /// This object retains ownership of the HANDLE when this accessor is used.
88 ///
89 /// \return
90 /// The STDOUT read HANDLE, or INVALID_HANDLE_VALUE if it is currently
91 /// invalid.
93
94 /// The STDIN write HANDLE accessor.
95 ///
96 /// This object retains ownership of the HANDLE when this accessor is used.
97 ///
98 /// \return
99 /// The STDIN write HANDLE, or INVALID_HANDLE_VALUE if it is currently
100 /// invalid.
102
103 /// The child-side stdin read HANDLE (pipe mode only).
105
106 /// The child-side stdout/stderr write HANDLE (pipe mode only).
108
109 Mode GetMode() const { return m_mode; };
110
111 /// Drains initialization sequences from the ConPTY output pipe.
112 ///
113 /// When a process first attaches to a ConPTY, Windows emits VT100/ANSI escape
114 /// sequences (ESC[2J for clear screen, ESC[H for cursor home and more) as
115 /// part of the PseudoConsole initialization. To prevent these sequences from
116 /// appearing in the debugger output (and flushing lldb's shell for instance)
117 /// we launch a short-lived dummy process that triggers the initialization,
118 /// then drain all output before launching the actual debuggee.
119 llvm::Error DrainInitSequences();
120
121 /// Returns a reference to the mutex used to synchronize access to the
122 /// ConPTY state.
123 std::mutex &GetMutex() { return m_mutex; };
124
125 /// Returns a reference to the condition variable used to signal state changes
126 /// to threads waiting on the ConPTY (e.g. waiting for output or shutdown).
127 std::condition_variable &GetCV() { return m_cv; };
128
129 /// Returns whether the ConPTY is in the process of shutting down.
130 ///
131 /// \return
132 /// A reference to the atomic bool that is set to true when the ConPTY
133 /// is stopping. Callers should check this in their read/write loops to
134 /// exit gracefully.
135 bool IsStopping() const { return m_stopping.load(); };
136
137 /// Sets the stopping flag to \p value, signalling to threads waiting on the
138 /// ConPTY that they should stop.
139 void SetStopping(bool value) { m_stopping = value; };
140
141protected:
142 HANDLE m_conpty_handle = ((HANDLE)(long long)-1);
143 HANDLE m_conpty_output = ((HANDLE)(long long)-1);
144 HANDLE m_conpty_input = ((HANDLE)(long long)-1);
145 // Pipe mode: child-side handles passed to CreateProcessW, closed after launch
146 HANDLE m_pipe_child_stdin = ((HANDLE)(long long)-1);
149 std::mutex m_mutex{};
150 std::condition_variable m_cv{};
151 std::atomic<bool> m_stopping = false;
152};
153} // namespace lldb_private
154
155#endif // LIBLLDB_HOST_WINDOWS_PSEUDOCONSOLE_H_
void * HPCON
void * HANDLE
PseudoConsole(const PseudoConsole &)=delete
PseudoConsole & operator=(const PseudoConsole &)=delete
llvm::Error OpenPseudoConsole()
Creates and opens a new ConPTY instance with a default console size of 80x25.
bool IsStopping() const
Returns whether the ConPTY is in the process of shutting down.
std::condition_variable & GetCV()
Returns a reference to the condition variable used to signal state changes to threads waiting on the ...
std::atomic< bool > m_stopping
llvm::Error CreateOverlappedPipePair(HANDLE &out_read, HANDLE &out_write, bool inheritable)
Creates a named pipe pair for overlapped I/O.
std::condition_variable m_cv
std::mutex & GetMutex()
Returns a reference to the mutex used to synchronize access to the ConPTY state.
llvm::Error OpenAnonymousPipes()
Creates a pair of anonymous pipes to use for stdio instead of a ConPTY.
void SetStopping(bool value)
Sets the stopping flag to value, signalling to threads waiting on the ConPTY that they should stop.
PseudoConsole & operator=(PseudoConsole &&)=delete
HANDLE GetSTDOUTHandle() const
The STDOUT read HANDLE accessor.
HANDLE GetChildStdinHandle() const
The child-side stdin read HANDLE (pipe mode only).
void Close()
Closes the ConPTY and invalidates its handle, without closing the STDIN and STDOUT pipes.
llvm::Error DrainInitSequences()
Drains initialization sequences from the ConPTY output pipe.
void ClosePseudoConsolePipes()
Closes the STDIN and STDOUT pipe handles and invalidates them.
HANDLE GetChildStdoutHandle() const
The child-side stdout/stderr write HANDLE (pipe mode only).
bool IsConnected() const
Returns whether the ConPTY and its pipes are currently open and valid.
void CloseAnonymousPipes()
Closes the child-side pipe handles (stdin read end and stdout/stderr write end) that were passed to C...
HPCON GetPseudoTerminalHandle()
The ConPTY HPCON handle accessor.
PseudoConsole(PseudoConsole &&)=delete
HANDLE GetSTDINHandle() const
The STDIN write HANDLE accessor.
A class that represents a running process on the host machine.