31 std::lock_guard<std::mutex> guard(
m_mutex);
51 llvm::consumeError(terminal.
SetEcho(
false));
54 const int pipe_read_fd =
m_pipe.GetReadFileDescriptor();
58 std::lock_guard<std::mutex> guard(
m_mutex);
84 if (llvm::Expected<size_t> bytes_read =
m_pipe.Read(&ch, 1)) {
92 "Pipe read failed: {0}");
101 std::lock_guard<std::mutex> guard(
m_mutex);
116 if (llvm::Error err =
m_pipe.Write(&ch, 1).takeError()) {
118 "Pipe write failed: {0}");
131 return !errorToBool(
m_pipe.Write(&ch, 1).takeError());
154IOHandlerProcessSTDIOWindows::IOHandlerProcessSTDIOWindows(
Process *process)
157 m_read_file(GetInputFD(),
File::eOpenOptionReadOnly, false),
159 CreateEvent(nullptr, FALSE,
162IOHandlerProcessSTDIOWindows::~IOHandlerProcessSTDIOWindows() {
163 if (m_interrupt_event != INVALID_HANDLE_VALUE)
164 ::CloseHandle(m_interrupt_event);
167void IOHandlerProcessSTDIOWindows::SetIsRunning(
bool running) {
168 std::lock_guard<std::mutex> guard(m_mutex);
170 m_is_running = running;
174IOHandlerProcessSTDIOWindows::ConsoleHasTextInput(
const HANDLE hStdin) {
177 DWORD bytesAvailable = 0;
178 if (PeekNamedPipe(hStdin,
nullptr, 0,
nullptr, &bytesAvailable,
nullptr)) {
179 if (bytesAvailable > 0)
184 INPUT_RECORD inputRecord;
186 if (!PeekConsoleInput(hStdin, &inputRecord, 1, &numRead))
187 return llvm::createStringError(
"failed to peek standard input");
192 if (inputRecord.EventType == KEY_EVENT &&
193 inputRecord.Event.KeyEvent.bKeyDown &&
194 inputRecord.Event.KeyEvent.uChar.AsciiChar != 0)
197 if (!ReadConsoleInput(hStdin, &inputRecord, 1, &numRead))
198 return llvm::createStringError(
"failed to read standard input");
202void IOHandlerProcessSTDIOWindows::Run() {
203 if (!m_read_file.IsValid()) {
211 HANDLE hStdin = m_read_file.GetWaitableHandle();
212 HANDLE waitHandles[2] = {hStdin, m_interrupt_event};
215 bool isConsole = GetConsoleMode(hStdin, &consoleMode) != 0;
220 DWORD oldConsoleMode = consoleMode;
221 SetConsoleMode(hStdin, consoleMode & ~ENABLE_LINE_INPUT & ~ENABLE_ECHO_INPUT);
225 std::lock_guard<std::mutex> guard(m_mutex);
230 DWORD result = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
234 case WAIT_OBJECT_0: {
236 auto hasInputOrErr = ConsoleHasTextInput(hStdin);
237 if (!hasInputOrErr) {
240 "failed to process debuggee's IO: {0}");
251 if (!ReadFile(hStdin, &ch, 1, &read,
nullptr) || read != 1)
255 m_process->PutSTDIN(&ch, 1, err);
260 case WAIT_OBJECT_0 + 1: {
261 ControlOp op = m_pending_op.exchange(eControlOpNone);
262 if (op == eControlOpQuit)
264 if (op == eControlOpInterrupt &&
266 m_process->SendAsyncInterrupt();
277 SetConsoleMode(hStdin, oldConsoleMode);
280void IOHandlerProcessSTDIOWindows::Cancel() {
281 std::lock_guard<std::mutex> guard(m_mutex);
284 m_pending_op.store(eControlOpQuit);
285 ::SetEvent(m_interrupt_event);
289bool IOHandlerProcessSTDIOWindows::Interrupt() {
291 m_pending_op.store(eControlOpInterrupt);
292 ::SetEvent(m_interrupt_event);
296 m_process->SendAsyncInterrupt();
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG_ERROR(log, error,...)
lldb_private::Status Select()
void FDSetRead(lldb::socket_t fd)
bool FDIsSetRead(lldb::socket_t fd) const
An abstract base class for files.
void SetIsRunning(bool running)
NativeFile m_write_file
Write to this file (usually the primary pty for getting io to debuggee)
bool Interrupt() override
NativeFile m_read_file
Read from this file (usually actual STDIN for LLDB)
IOHandlerProcessSTDIO(Process *process, int write_fd)
IOHandler(Debugger &debugger, IOHandler::Type type)
A plug-in interface definition class for debugging a process.
bool Fail() const
Test for error condition.
A RAII-friendly terminal state saving/restoring class.
llvm::Error SetEcho(bool enabled)
llvm::Error SetCanonical(bool enabled)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
bool StateIsRunningState(lldb::StateType state)
Check if a state represents a state where the process or thread is running.