win: prevent tty event explosion machine hang
The tty subsystem on Windows was listening for console events from all processes to detect when our console window was being resized. This could cause an explosion in the number of events queued by the system when running many console applications in parallel that all wrote to their console quickly. The end result was a complete machine hang. Now we determine, whenever possible, what our corresponding conhost.exe process is and listen for console events from that process only. This detection does not work in 32-bit applications running on 64-bit Windows so those default to the old behavior of listening to all processes. PR-URL: https://github.com/libuv/libuv/pull/2308 Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com> Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
This commit is contained in:
parent
a5d3743778
commit
dabc737d78
@ -2280,6 +2280,8 @@ static void uv__determine_vterm_state(HANDLE handle) {
|
||||
|
||||
static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO sb_info;
|
||||
NTSTATUS status;
|
||||
ULONG_PTR conhost_pid;
|
||||
MSG msg;
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))
|
||||
@ -2288,14 +2290,29 @@ static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) {
|
||||
uv__tty_console_width = sb_info.dwSize.X;
|
||||
uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
|
||||
|
||||
if (pSetWinEventHook == NULL)
|
||||
if (pSetWinEventHook == NULL || pNtQueryInformationProcess == NULL)
|
||||
return 0;
|
||||
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(),
|
||||
ProcessConsoleHostProcess,
|
||||
&conhost_pid,
|
||||
sizeof(conhost_pid),
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
/* We couldn't retrieve our console host process, probably because this
|
||||
* is a 32-bit process running on 64-bit Windows. Fall back to receiving
|
||||
* console events from all processes. */
|
||||
conhost_pid = 0;
|
||||
|
||||
/* Ensure the PID is a multiple of 4, which is required by SetWinEventHook */
|
||||
conhost_pid &= ~(ULONG_PTR)0x3;
|
||||
|
||||
if (!pSetWinEventHook(EVENT_CONSOLE_LAYOUT,
|
||||
EVENT_CONSOLE_LAYOUT,
|
||||
NULL,
|
||||
uv__tty_console_resize_event,
|
||||
0,
|
||||
(DWORD)conhost_pid,
|
||||
0,
|
||||
WINEVENT_OUTOFCONTEXT))
|
||||
return 0;
|
||||
|
||||
@ -34,6 +34,7 @@ sNtSetInformationFile pNtSetInformationFile;
|
||||
sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
|
||||
sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
||||
sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||
sNtQueryInformationProcess pNtQueryInformationProcess;
|
||||
|
||||
/* Kernel32 function pointers */
|
||||
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||
@ -106,6 +107,13 @@ void uv_winapi_init(void) {
|
||||
uv_fatal_error(GetLastError(), "GetProcAddress");
|
||||
}
|
||||
|
||||
pNtQueryInformationProcess = (sNtQueryInformationProcess) GetProcAddress(
|
||||
ntdll_module,
|
||||
"NtQueryInformationProcess");
|
||||
if (pNtQueryInformationProcess == NULL) {
|
||||
uv_fatal_error(GetLastError(), "GetProcAddress");
|
||||
}
|
||||
|
||||
kernel32_module = GetModuleHandleA("kernel32.dll");
|
||||
if (kernel32_module == NULL) {
|
||||
uv_fatal_error(GetLastError(), "GetModuleHandleA");
|
||||
|
||||
@ -4436,6 +4436,10 @@ typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
|
||||
# define SystemProcessorPerformanceInformation 8
|
||||
#endif
|
||||
|
||||
#ifndef ProcessConsoleHostProcess
|
||||
# define ProcessConsoleHostProcess 49
|
||||
#endif
|
||||
|
||||
#ifndef FILE_DEVICE_FILE_SYSTEM
|
||||
# define FILE_DEVICE_FILE_SYSTEM 0x00000009
|
||||
#endif
|
||||
@ -4578,6 +4582,13 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
|
||||
BOOLEAN RestartScan
|
||||
);
|
||||
|
||||
typedef NTSTATUS (NTAPI *sNtQueryInformationProcess)
|
||||
(HANDLE ProcessHandle,
|
||||
UINT ProcessInformationClass,
|
||||
PVOID ProcessInformation,
|
||||
ULONG Length,
|
||||
PULONG ReturnLength);
|
||||
|
||||
/*
|
||||
* Kernel32 headers
|
||||
*/
|
||||
@ -4718,6 +4729,7 @@ extern sNtSetInformationFile pNtSetInformationFile;
|
||||
extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
|
||||
extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
||||
extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||
extern sNtQueryInformationProcess pNtQueryInformationProcess;
|
||||
|
||||
/* Kernel32 function pointers */
|
||||
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user