LLDB mainline
MainLoopWindows.cpp
Go to the documentation of this file.
1//===-- MainLoopWindows.cpp -----------------------------------------------===//
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#include "lldb/Host/Config.h"
11#include "lldb/Utility/Status.h"
12#include "llvm/Config/llvm-config.h"
13#include <algorithm>
14#include <cassert>
15#include <cerrno>
16#include <csignal>
17#include <ctime>
18#include <vector>
19#include <winsock2.h>
20
21using namespace lldb;
22using namespace lldb_private;
23
25 m_trigger_event = WSACreateEvent();
26 assert(m_trigger_event != WSA_INVALID_EVENT);
27}
28
30 assert(m_read_fds.empty());
31 BOOL result = WSACloseEvent(m_trigger_event);
32 assert(result == TRUE);
34}
35
36llvm::Expected<size_t> MainLoopWindows::Poll() {
37 std::vector<WSAEVENT> events;
38 events.reserve(m_read_fds.size() + 1);
39 for (auto &[fd, info] : m_read_fds) {
40 int result = WSAEventSelect(fd, info.event, FD_READ | FD_ACCEPT | FD_CLOSE);
41 assert(result == 0);
43
44 events.push_back(info.event);
45 }
46 events.push_back(m_trigger_event);
47
48 DWORD result = WSAWaitForMultipleEvents(events.size(), events.data(), FALSE,
49 WSA_INFINITE, FALSE);
50
51 for (auto &fd : m_read_fds) {
52 int result = WSAEventSelect(fd.first, WSA_INVALID_EVENT, 0);
53 assert(result == 0);
55 }
56
57 if (result >= WSA_WAIT_EVENT_0 && result <= WSA_WAIT_EVENT_0 + events.size())
58 return result - WSA_WAIT_EVENT_0;
59
60 return llvm::createStringError(llvm::inconvertibleErrorCode(),
61 "WSAWaitForMultipleEvents failed");
62}
63
66 const Callback &callback, Status &error) {
67 if (!object_sp || !object_sp->IsValid()) {
68 error.SetErrorString("IO object is not valid.");
69 return nullptr;
70 }
71 if (object_sp->GetFdType() != IOObject::eFDTypeSocket) {
72 error.SetErrorString(
73 "MainLoopWindows: non-socket types unsupported on Windows");
74 return nullptr;
75 }
76
77 WSAEVENT event = WSACreateEvent();
78 if (event == WSA_INVALID_EVENT) {
79 error.SetErrorStringWithFormat("Cannot create monitoring event.");
80 return nullptr;
81 }
82
83 const bool inserted =
85 .try_emplace(object_sp->GetWaitableHandle(), FdInfo{event, callback})
86 .second;
87 if (!inserted) {
88 WSACloseEvent(event);
89 error.SetErrorStringWithFormat("File descriptor %d already monitored.",
90 object_sp->GetWaitableHandle());
91 return nullptr;
92 }
93
94 return CreateReadHandle(object_sp);
95}
96
98 auto it = m_read_fds.find(handle);
99 assert(it != m_read_fds.end());
100 BOOL result = WSACloseEvent(it->second.event);
101 assert(result == TRUE);
103 m_read_fds.erase(it);
104}
105
107 auto it = m_read_fds.find(handle);
108 if (it != m_read_fds.end())
109 it->second.callback(*this); // Do the work
110}
111
113 m_terminate_request = false;
114
116
117 // run until termination or until we run out of things to listen to
118 while (!m_terminate_request && !m_read_fds.empty()) {
119
120 llvm::Expected<size_t> signaled_event = Poll();
121 if (!signaled_event)
122 return Status(signaled_event.takeError());
123
124 if (*signaled_event < m_read_fds.size()) {
125 auto &KV = *std::next(m_read_fds.begin(), *signaled_event);
126 ProcessReadObject(KV.first);
127 } else {
128 assert(*signaled_event == m_read_fds.size());
129 WSAResetEvent(m_trigger_event);
130 }
132 }
133 return Status();
134}
135
137 WSASetEvent(m_trigger_event);
138}
static llvm::raw_ostream & error(Stream &strm)
std::unique_ptr< ReadHandle > ReadHandleUP
Definition: MainLoopBase.h:44
ReadHandleUP CreateReadHandle(const lldb::IOObjectSP &object_sp)
Definition: MainLoopBase.h:66
std::function< void(MainLoopBase &)> Callback
Definition: MainLoopBase.h:46
llvm::Expected< size_t > Poll()
llvm::DenseMap< IOObject::WaitableHandle, FdInfo > m_read_fds
ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, const Callback &callback, Status &error) override
void UnregisterReadObject(IOObject::WaitableHandle handle) override
void ProcessReadObject(IOObject::WaitableHandle handle)
An error handling class.
Definition: Status.h:44
#define UNUSED_IF_ASSERT_DISABLED(x)
Definition: lldb-defines.h:140
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::IOObject > IOObjectSP
Definition: lldb-forward.h:360