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 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 MainLoopWindows::MainLoopWindows() {
25  m_trigger_event = WSACreateEvent();
26  assert(m_trigger_event != WSA_INVALID_EVENT);
27 }
28 
29 MainLoopWindows::~MainLoopWindows() {
30  assert(m_read_fds.empty());
31  BOOL result = WSACloseEvent(m_trigger_event);
32  assert(result == TRUE);
33  (void)result;
34 }
35 
36 llvm::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);
42  (void)result;
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);
54  (void)result;
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 
65 MainLoopWindows::RegisterReadObject(const IOObjectSP &object_sp,
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 =
84  m_read_fds
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 
97 void MainLoopWindows::UnregisterReadObject(IOObject::WaitableHandle handle) {
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);
102  (void)result;
103  m_read_fds.erase(it);
104 }
105 
106 void MainLoopWindows::ProcessReadObject(IOObject::WaitableHandle handle) {
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 
112 Status MainLoopWindows::Run() {
113  m_terminate_request = false;
114 
115  Status error;
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  }
131  ProcessPendingCallbacks();
132  }
133  return Status();
134 }
135 
136 void MainLoopWindows::TriggerPendingCallbacks() {
137  WSASetEvent(m_trigger_event);
138 }
MainLoopWindows.h
lldb_private::MainLoopBase::ReadHandleUP
std::unique_ptr< ReadHandle > ReadHandleUP
Definition: MainLoopBase.h:44
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::IOObject::WaitableHandle
int WaitableHandle
Definition: IOObject.h:29
lldb_private::Status
Definition: Status.h:44
Status.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::MainLoopBase::Callback
std::function< void(MainLoopBase &)> Callback
Definition: MainLoopBase.h:46
lldb
Definition: SBAddress.h:15
lldb_private::MainLoopWindows::FdInfo
Definition: MainLoopWindows.h:43