1 //===-- Listener.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 
9 #include "lldb/Utility/Listener.h"
10 
11 #include "lldb/Utility/Broadcaster.h"
12 #include "lldb/Utility/ConstString.h"
13 #include "lldb/Utility/Event.h"
14 #include "lldb/Utility/Log.h"
15 #include "lldb/Utility/Logging.h"
16 
17 #include "llvm/ADT/Optional.h"
18 
19 #include <algorithm>
20 #include <memory>
21 #include <utility>
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 namespace {
27 class BroadcasterManagerWPMatcher {
28 public:
29   BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)
30       : m_manager_sp(std::move(manager_sp)) {}
31   bool operator()(const BroadcasterManagerWP &input_wp) const {
32     BroadcasterManagerSP input_sp = input_wp.lock();
33     return (input_sp && input_sp == m_manager_sp);
34   }
35 
36   BroadcasterManagerSP m_manager_sp;
37 };
38 } // anonymous namespace
39 
40 Listener::Listener(const char *name)
41     : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
42       m_events_mutex() {
43   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
44   if (log != nullptr)
45     LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this),
46               m_name.c_str());
47 }
48 
49 Listener::~Listener() {
50   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
51 
52   Clear();
53 
54   LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
55             __FUNCTION__, m_name.c_str());
56 }
57 
58 void Listener::Clear() {
59   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
60   std::lock_guard<std::recursive_mutex> broadcasters_guard(
61       m_broadcasters_mutex);
62   broadcaster_collection::iterator pos, end = m_broadcasters.end();
63   for (pos = m_broadcasters.begin(); pos != end; ++pos) {
64     Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
65     if (broadcaster_sp)
66       broadcaster_sp->RemoveListener(this, pos->second.event_mask);
67   }
68   m_broadcasters.clear();
69 
70   std::lock_guard<std::mutex> events_guard(m_events_mutex);
71   m_events.clear();
72   size_t num_managers = m_broadcaster_managers.size();
73 
74   for (size_t i = 0; i < num_managers; i++) {
75     BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
76     if (manager_sp)
77       manager_sp->RemoveListener(this);
78   }
79 
80   LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
81             __FUNCTION__, m_name.c_str());
82 }
83 
84 uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
85                                            uint32_t event_mask) {
86   if (broadcaster) {
87     // Scope for "locker"
88     // Tell the broadcaster to add this object as a listener
89     {
90       std::lock_guard<std::recursive_mutex> broadcasters_guard(
91           m_broadcasters_mutex);
92       Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
93       m_broadcasters.insert(
94           std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
95     }
96 
97     uint32_t acquired_mask =
98         broadcaster->AddListener(this->shared_from_this(), event_mask);
99 
100     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
101     if (log != nullptr)
102       LLDB_LOGF(log,
103                 "%p Listener::StartListeningForEvents (broadcaster = %p, "
104                 "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
105                 static_cast<void *>(this), static_cast<void *>(broadcaster),
106                 event_mask, acquired_mask, m_name.c_str());
107 
108     return acquired_mask;
109   }
110   return 0;
111 }
112 
113 uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
114                                            uint32_t event_mask,
115                                            HandleBroadcastCallback callback,
116                                            void *callback_user_data) {
117   if (broadcaster) {
118     // Scope for "locker"
119     // Tell the broadcaster to add this object as a listener
120     {
121       std::lock_guard<std::recursive_mutex> broadcasters_guard(
122           m_broadcasters_mutex);
123       Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
124       m_broadcasters.insert(std::make_pair(
125           impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
126     }
127 
128     uint32_t acquired_mask =
129         broadcaster->AddListener(this->shared_from_this(), event_mask);
130 
131     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
132     if (log != nullptr) {
133       void **pointer = reinterpret_cast<void **>(&callback);
134       LLDB_LOGF(log,
135                 "%p Listener::StartListeningForEvents (broadcaster = %p, "
136                 "mask = 0x%8.8x, callback = %p, user_data = %p) "
137                 "acquired_mask = 0x%8.8x for %s",
138                 static_cast<void *>(this), static_cast<void *>(broadcaster),
139                 event_mask, *pointer, static_cast<void *>(callback_user_data),
140                 acquired_mask, m_name.c_str());
141     }
142 
143     return acquired_mask;
144   }
145   return 0;
146 }
147 
148 bool Listener::StopListeningForEvents(Broadcaster *broadcaster,
149                                       uint32_t event_mask) {
150   if (broadcaster) {
151     // Scope for "locker"
152     {
153       std::lock_guard<std::recursive_mutex> broadcasters_guard(
154           m_broadcasters_mutex);
155       m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
156     }
157     // Remove the broadcaster from our set of broadcasters
158     return broadcaster->RemoveListener(this->shared_from_this(), event_mask);
159   }
160 
161   return false;
162 }
163 
164 // Called when a Broadcaster is in its destructor. We need to remove all
165 // knowledge of this broadcaster and any events that it may have queued up
166 void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) {
167   // Scope for "broadcasters_locker"
168   {
169     std::lock_guard<std::recursive_mutex> broadcasters_guard(
170         m_broadcasters_mutex);
171     m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
172   }
173 
174   // Scope for "event_locker"
175   {
176     std::lock_guard<std::mutex> events_guard(m_events_mutex);
177     // Remove all events for this broadcaster object.
178     event_collection::iterator pos = m_events.begin();
179     while (pos != m_events.end()) {
180       if ((*pos)->GetBroadcaster() == broadcaster)
181         pos = m_events.erase(pos);
182       else
183         ++pos;
184     }
185   }
186 }
187 
188 void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) {
189   // Just need to remove this broadcast manager from the list of managers:
190   broadcaster_manager_collection::iterator iter,
191       end_iter = m_broadcaster_managers.end();
192   BroadcasterManagerWP manager_wp;
193 
194   BroadcasterManagerWPMatcher matcher(std::move(manager_sp));
195   iter = std::find_if<broadcaster_manager_collection::iterator,
196                       BroadcasterManagerWPMatcher>(
197       m_broadcaster_managers.begin(), end_iter, matcher);
198   if (iter != end_iter)
199     m_broadcaster_managers.erase(iter);
200 }
201 
202 void Listener::AddEvent(EventSP &event_sp) {
203   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
204   if (log != nullptr)
205     LLDB_LOGF(log, "%p Listener('%s')::AddEvent (event_sp = {%p})",
206               static_cast<void *>(this), m_name.c_str(),
207               static_cast<void *>(event_sp.get()));
208 
209   std::lock_guard<std::mutex> guard(m_events_mutex);
210   m_events.push_back(event_sp);
211   m_events_condition.notify_all();
212 }
213 
214 class EventBroadcasterMatches {
215 public:
216   EventBroadcasterMatches(Broadcaster *broadcaster)
217       : m_broadcaster(broadcaster) {}
218 
219   bool operator()(const EventSP &event_sp) const {
220     return event_sp->BroadcasterIs(m_broadcaster);
221   }
222 
223 private:
224   Broadcaster *m_broadcaster;
225 };
226 
227 class EventMatcher {
228 public:
229   EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names,
230                uint32_t num_broadcaster_names, uint32_t event_type_mask)
231       : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names),
232         m_num_broadcaster_names(num_broadcaster_names),
233         m_event_type_mask(event_type_mask) {}
234 
235   bool operator()(const EventSP &event_sp) const {
236     if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster))
237       return false;
238 
239     if (m_broadcaster_names) {
240       bool found_source = false;
241       ConstString event_broadcaster_name =
242           event_sp->GetBroadcaster()->GetBroadcasterName();
243       for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) {
244         if (m_broadcaster_names[i] == event_broadcaster_name) {
245           found_source = true;
246           break;
247         }
248       }
249       if (!found_source)
250         return false;
251     }
252 
253     return m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType();
254   }
255 
256 private:
257   Broadcaster *m_broadcaster;
258   const ConstString *m_broadcaster_names;
259   const uint32_t m_num_broadcaster_names;
260   const uint32_t m_event_type_mask;
261 };
262 
263 bool Listener::FindNextEventInternal(
264     std::unique_lock<std::mutex> &lock,
265     Broadcaster *broadcaster,             // nullptr for any broadcaster
266     const ConstString *broadcaster_names, // nullptr for any event
267     uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp,
268     bool remove) {
269   // NOTE: callers of this function must lock m_events_mutex using a
270   // Mutex::Locker
271   // and pass the locker as the first argument. m_events_mutex is no longer
272   // recursive.
273   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
274 
275   if (m_events.empty())
276     return false;
277 
278   Listener::event_collection::iterator pos = m_events.end();
279 
280   if (broadcaster == nullptr && broadcaster_names == nullptr &&
281       event_type_mask == 0) {
282     pos = m_events.begin();
283   } else {
284     pos = std::find_if(m_events.begin(), m_events.end(),
285                        EventMatcher(broadcaster, broadcaster_names,
286                                     num_broadcaster_names, event_type_mask));
287   }
288 
289   if (pos != m_events.end()) {
290     event_sp = *pos;
291 
292     if (log != nullptr)
293       LLDB_LOGF(log,
294                 "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, "
295                 "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, "
296                 "remove=%i) event %p",
297                 static_cast<void *>(this), GetName(),
298                 static_cast<void *>(broadcaster),
299                 static_cast<const void *>(broadcaster_names),
300                 num_broadcaster_names, event_type_mask, remove,
301                 static_cast<void *>(event_sp.get()));
302 
303     if (remove) {
304       m_events.erase(pos);
305       // Unlock the event queue here.  We've removed this event and are about
306       // to return it so it should be okay to get the next event off the queue
307       // here - and it might be useful to do that in the "DoOnRemoval".
308       lock.unlock();
309       event_sp->DoOnRemoval();
310     }
311     return true;
312   }
313 
314   event_sp.reset();
315   return false;
316 }
317 
318 Event *Listener::PeekAtNextEvent() {
319   std::unique_lock<std::mutex> guard(m_events_mutex);
320   EventSP event_sp;
321   if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false))
322     return event_sp.get();
323   return nullptr;
324 }
325 
326 Event *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) {
327   std::unique_lock<std::mutex> guard(m_events_mutex);
328   EventSP event_sp;
329   if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false))
330     return event_sp.get();
331   return nullptr;
332 }
333 
334 Event *
335 Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster,
336                                                 uint32_t event_type_mask) {
337   std::unique_lock<std::mutex> guard(m_events_mutex);
338   EventSP event_sp;
339   if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask,
340                             event_sp, false))
341     return event_sp.get();
342   return nullptr;
343 }
344 
345 bool Listener::GetEventInternal(
346     const Timeout<std::micro> &timeout,
347     Broadcaster *broadcaster,             // nullptr for any broadcaster
348     const ConstString *broadcaster_names, // nullptr for any event
349     uint32_t num_broadcaster_names, uint32_t event_type_mask,
350     EventSP &event_sp) {
351   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
352   LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name);
353 
354   std::unique_lock<std::mutex> lock(m_events_mutex);
355 
356   while (true) {
357     if (FindNextEventInternal(lock, broadcaster, broadcaster_names,
358                               num_broadcaster_names, event_type_mask, event_sp,
359                               true)) {
360       return true;
361     } else {
362       std::cv_status result = std::cv_status::no_timeout;
363       if (!timeout)
364         m_events_condition.wait(lock);
365       else
366         result = m_events_condition.wait_for(lock, *timeout);
367 
368       if (result == std::cv_status::timeout) {
369         log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
370         LLDB_LOGF(log, "%p Listener::GetEventInternal() timed out for %s",
371                   static_cast<void *>(this), m_name.c_str());
372         return false;
373       } else if (result != std::cv_status::no_timeout) {
374         log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
375         LLDB_LOGF(log, "%p Listener::GetEventInternal() unknown error for %s",
376                   static_cast<void *>(this), m_name.c_str());
377         return false;
378       }
379     }
380   }
381 
382   return false;
383 }
384 
385 bool Listener::GetEventForBroadcasterWithType(
386     Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp,
387     const Timeout<std::micro> &timeout) {
388   return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask,
389                           event_sp);
390 }
391 
392 bool Listener::GetEventForBroadcaster(Broadcaster *broadcaster,
393                                       EventSP &event_sp,
394                                       const Timeout<std::micro> &timeout) {
395   return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp);
396 }
397 
398 bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
399   return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
400 }
401 
402 size_t Listener::HandleBroadcastEvent(EventSP &event_sp) {
403   size_t num_handled = 0;
404   std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
405   Broadcaster *broadcaster = event_sp->GetBroadcaster();
406   if (!broadcaster)
407     return 0;
408   broadcaster_collection::iterator pos;
409   broadcaster_collection::iterator end = m_broadcasters.end();
410   Broadcaster::BroadcasterImplSP broadcaster_impl_sp(
411       broadcaster->GetBroadcasterImpl());
412   for (pos = m_broadcasters.find(broadcaster_impl_sp);
413        pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) {
414     BroadcasterInfo info = pos->second;
415     if (event_sp->GetType() & info.event_mask) {
416       if (info.callback != nullptr) {
417         info.callback(event_sp, info.callback_user_data);
418         ++num_handled;
419       }
420     }
421   }
422   return num_handled;
423 }
424 
425 uint32_t
426 Listener::StartListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
427                                      const BroadcastEventSpec &event_spec) {
428   if (!manager_sp)
429     return 0;
430 
431   // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
432   // avoid violating the lock hierarchy (manager before broadcasters).
433   std::lock_guard<std::recursive_mutex> manager_guard(
434       manager_sp->m_manager_mutex);
435   std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
436 
437   uint32_t bits_acquired = manager_sp->RegisterListenerForEvents(
438       this->shared_from_this(), event_spec);
439   if (bits_acquired) {
440     broadcaster_manager_collection::iterator iter,
441         end_iter = m_broadcaster_managers.end();
442     BroadcasterManagerWP manager_wp(manager_sp);
443     BroadcasterManagerWPMatcher matcher(manager_sp);
444     iter = std::find_if<broadcaster_manager_collection::iterator,
445                         BroadcasterManagerWPMatcher>(
446         m_broadcaster_managers.begin(), end_iter, matcher);
447     if (iter == end_iter)
448       m_broadcaster_managers.push_back(manager_wp);
449   }
450 
451   return bits_acquired;
452 }
453 
454 bool Listener::StopListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
455                                          const BroadcastEventSpec &event_spec) {
456   if (!manager_sp)
457     return false;
458 
459   std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
460   return manager_sp->UnregisterListenerForEvents(this->shared_from_this(),
461                                                  event_spec);
462 }
463 
464 ListenerSP Listener::MakeListener(const char *name) {
465   return ListenerSP(new Listener(name));
466 }
467