================ @@ -31,6 +34,122 @@ static DWORD ToTimeout(std::optional<MainLoopWindows::TimePoint> point) { return ceil<milliseconds>(dur).count(); } +namespace { + +class PipeEvent : public MainLoopWindows::IOEvent { +public: + explicit PipeEvent(HANDLE handle) + : IOEvent((IOObject::WaitableHandle)CreateEventW( + NULL, /*bManualReset=*/FALSE, + /*bInitialState=*/FALSE, NULL)), + m_handle(handle), m_ready(CreateEventW(NULL, /*bManualReset=*/FALSE, + /*bInitialState=*/FALSE, NULL)) { + assert(m_event && m_ready); + } + + ~PipeEvent() override { + if (m_monitor_thread.joinable()) { + m_stopped = true; + SetEvent(m_ready); + // Keep trying to cancel ReadFile() until the thread exits. + do { + CancelIoEx((HANDLE)m_handle, /*lpOverlapped=*/NULL); + } while (WaitForSingleObject(m_monitor_thread.native_handle(), 1) == + WAIT_TIMEOUT); + m_monitor_thread.join(); + } + CloseHandle((HANDLE)m_event); + CloseHandle(m_ready); + } + + void WillPoll() override { + if (!m_monitor_thread.joinable()) + m_monitor_thread = std::thread(&PipeEvent::Monitor, this); + } + + void Disarm() override { SetEvent(m_ready); } + + /// Monitors the handle performing a zero byte read to determine when data is + /// avaiable. + void Monitor() { + do { + char buf[1]; + DWORD bytes_read = 0; + OVERLAPPED ov = {0}; + // Block on a 0-byte read; this will only resume when data is + // available in the pipe. The pipe must be PIPE_WAIT or this thread + // will spin. + BOOL success = + ReadFile(m_handle, buf, /*nNumberOfBytesToRead=*/0, &bytes_read, &ov); + DWORD bytes_available = 0; + DWORD err = GetLastError(); ---------------- slydiman wrote:
Don't call GetLastError() if ReadFile returned TRUE! https://github.com/llvm/llvm-project/pull/145621 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits