LLDB mainline
PseudoConsole.cpp
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
10
11#include <mutex>
12
16
17#include "llvm/Support/Errc.h"
18#include "llvm/Support/Errno.h"
19
20using namespace lldb_private;
21
22typedef HRESULT(WINAPI *CreatePseudoConsole_t)(COORD size, HANDLE hInput,
23 HANDLE hOutput, DWORD dwFlags,
24 HPCON *phPC);
25
26typedef VOID(WINAPI *ClosePseudoConsole_t)(HPCON hPC);
27
28struct Kernel32 {
30 hModule = LoadLibraryW(L"kernel32.dll");
31 if (!hModule) {
32 llvm::Error err = llvm::errorCodeToError(
33 std::error_code(GetLastError(), std::system_category()));
34 LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(err),
35 "Could not load kernel32: {0}");
36 return;
37 }
39 (CreatePseudoConsole_t)GetProcAddress(hModule, "CreatePseudoConsole");
41 (ClosePseudoConsole_t)GetProcAddress(hModule, "ClosePseudoConsole");
43 }
44
45 HRESULT CreatePseudoConsole(COORD size, HANDLE hInput, HANDLE hOutput,
46 DWORD dwFlags, HPCON *phPC) {
47 assert(CreatePseudoConsole_ && "CreatePseudoConsole is not available!");
48 return CreatePseudoConsole_(size, hInput, hOutput, dwFlags, phPC);
49 }
50
52 assert(ClosePseudoConsole_ && "ClosePseudoConsole is not available!");
53 return ClosePseudoConsole_(hPC);
54 }
55
56 bool IsConPTYAvailable() { return isAvailable; }
57
58private:
59 HMODULE hModule;
63};
64
66
68 if (!kernel32.IsConPTYAvailable())
69 return llvm::make_error<llvm::StringError>("ConPTY is not available",
70 llvm::errc::io_error);
71 HRESULT hr;
72 HANDLE hInputRead = INVALID_HANDLE_VALUE;
73 HANDLE hInputWrite = INVALID_HANDLE_VALUE;
74 HANDLE hOutputRead = INVALID_HANDLE_VALUE;
75 HANDLE hOutputWrite = INVALID_HANDLE_VALUE;
76
77 wchar_t pipe_name[MAX_PATH];
78 swprintf(pipe_name, MAX_PATH, L"\\\\.\\pipe\\conpty-lldb-%d-%p",
79 GetCurrentProcessId(), this);
80
81 // A 4096 bytes buffer should be large enough for the majority of console
82 // burst outputs.
83 hOutputRead =
84 CreateNamedPipeW(pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
85 PIPE_TYPE_BYTE | PIPE_WAIT, 1, 4096, 4096, 0, NULL);
86 hOutputWrite = CreateFileW(pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
87 FILE_ATTRIBUTE_NORMAL, NULL);
88
89 if (!CreatePipe(&hInputRead, &hInputWrite, NULL, 0))
90 return llvm::errorCodeToError(
91 std::error_code(GetLastError(), std::system_category()));
92
93 COORD consoleSize{80, 25};
94 HPCON hPC = INVALID_HANDLE_VALUE;
95 hr = kernel32.CreatePseudoConsole(consoleSize, hInputRead, hOutputWrite, 0,
96 &hPC);
97 CloseHandle(hInputRead);
98 CloseHandle(hOutputWrite);
99
100 if (FAILED(hr)) {
101 CloseHandle(hInputWrite);
102 CloseHandle(hOutputRead);
103 return llvm::make_error<llvm::StringError>(
104 "Failed to create Windows ConPTY pseudo terminal",
105 llvm::errc::io_error);
106 }
107
108 DWORD mode = PIPE_NOWAIT;
109 SetNamedPipeHandleState(hOutputRead, &mode, NULL, NULL);
110
111 m_conpty_handle = hPC;
112 m_conpty_output = hOutputRead;
113 m_conpty_input = hInputWrite;
114
115 return llvm::Error::success();
116}
117
119 if (m_conpty_handle != INVALID_HANDLE_VALUE)
120 kernel32.ClosePseudoConsole(m_conpty_handle);
121 CloseHandle(m_conpty_input);
122 CloseHandle(m_conpty_output);
123 m_conpty_handle = INVALID_HANDLE_VALUE;
124 m_conpty_input = INVALID_HANDLE_VALUE;
125 m_conpty_output = INVALID_HANDLE_VALUE;
126}
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:392
HRESULT(WINAPI * CreatePseudoConsole_t)(COORD size, HANDLE hInput, HANDLE hOutput, DWORD dwFlags, HPCON *phPC)
VOID(WINAPI * ClosePseudoConsole_t)(HPCON hPC)
static Kernel32 kernel32
void * HPCON
void * HANDLE
void Close()
Close the ConPTY, its read/write handles and invalidate them.
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.
Definition Log.h:332
VOID ClosePseudoConsole(HPCON hPC)
CreatePseudoConsole_t CreatePseudoConsole_
HMODULE hModule
bool IsConPTYAvailable()
HRESULT CreatePseudoConsole(COORD size, HANDLE hInput, HANDLE hOutput, DWORD dwFlags, HPCON *phPC)
ClosePseudoConsole_t ClosePseudoConsole_