diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/Core/Broadcaster.cpp | 190 | ||||
-rw-r--r-- | lldb/source/Core/Event.cpp | 33 | ||||
-rw-r--r-- | lldb/source/Core/Listener.cpp | 113 | ||||
-rw-r--r-- | lldb/source/Host/posix/HostThreadPosix.cpp | 18 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 68 |
5 files changed, 232 insertions, 190 deletions
diff --git a/lldb/source/Core/Broadcaster.cpp b/lldb/source/Core/Broadcaster.cpp index 3f125183d0b..ec91f8d8a7f 100644 --- a/lldb/source/Core/Broadcaster.cpp +++ b/lldb/source/Core/Broadcaster.cpp @@ -61,6 +61,33 @@ Broadcaster::CheckInWithManager () } void +Broadcaster::BroadcasterImpl::ListenerIterator (std::function <bool (const lldb::ListenerSP &listener_sp, uint32_t &event_mask)> const &callback) +{ + // Private iterator that should be used by everyone except BroadcasterImpl::RemoveListener(). + // We have weak pointers to our listeners which means that at any point the listener can + // expire which means we will need to take it out of our list. To take care of this, we + // iterate and check that the weak pointer can be made into a valid shared pointer before + // we call the callback. If the weak pointer has expired, we remove it from our list. + collection::iterator pos = m_listeners.begin(); + while (pos != m_listeners.end()) + { + lldb::ListenerSP curr_listener_sp(pos->first.lock()); + if (curr_listener_sp) + { + if (callback(curr_listener_sp, pos->second)) + ++pos; // Keep iterating + else + return; // Done iterating + } + else + { + // The listener has been expired. Remove this entry. + pos = m_listeners.erase(pos); + } + } +} + +void Broadcaster::BroadcasterImpl::Clear() { Mutex::Locker listeners_locker(m_listeners_mutex); @@ -68,10 +95,11 @@ Broadcaster::BroadcasterImpl::Clear() // Make sure the listener forgets about this broadcaster. We do // this in the broadcaster in case the broadcaster object initiates // the removal. - - collection::iterator pos, end = m_listeners.end(); - for (pos = m_listeners.begin(); pos != end; ++pos) - pos->first->BroadcasterWillDestruct (&m_broadcaster); + + ListenerIterator([this](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool { + curr_listener_sp->BroadcasterWillDestruct (&m_broadcaster); + return true; // Keep iterating + }); m_listeners.clear(); } @@ -114,57 +142,45 @@ Broadcaster::BroadcasterImpl::GetEventNames (Stream &s, uint32_t event_mask, boo } void -Broadcaster::AddInitialEventsToListener (lldb::ListenerSP listener_sp, uint32_t requested_events) +Broadcaster::AddInitialEventsToListener (const lldb::ListenerSP &listener_sp, uint32_t requested_events) { } uint32_t -Broadcaster::BroadcasterImpl::AddListener (lldb::ListenerSP listener_sp, uint32_t event_mask) +Broadcaster::BroadcasterImpl::AddListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask) { if (!listener_sp) return 0; Mutex::Locker locker(m_listeners_mutex); - collection::iterator pos, end = m_listeners.end(); - collection::iterator existing_pos = end; // See if we already have this listener, and if so, update its mask - uint32_t taken_event_types = 0; - for (pos = m_listeners.begin(); pos != end; ++pos) - { - if (pos->first == listener_sp) - existing_pos = pos; - // For now don't descriminate on who gets what - // FIXME: Implement "unique listener for this bit" mask - // taken_event_types |= pos->second; - } - // Each event bit in a Broadcaster object can only be used - // by one listener - uint32_t available_event_types = ~taken_event_types & event_mask; + bool handled = false; - if (available_event_types) - { - // If we didn't find our listener, add it - if (existing_pos == end) + ListenerIterator([this, &listener_sp, &handled, event_mask](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool { + if (curr_listener_sp == listener_sp) { - // Grant a new listener the available event bits - m_listeners.push_back(std::make_pair(listener_sp, available_event_types)); - } - else - { - // Grant the existing listener the available event bits - existing_pos->second |= available_event_types; + handled = true; + curr_event_mask |= event_mask; + m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask); + return false; // Stop iterating } + return true; // Keep iterating + }); + + if (!handled) + { + // Grant a new listener the available event bits + m_listeners.push_back(std::make_pair(lldb::ListenerWP(listener_sp), event_mask)); // Individual broadcasters decide whether they have outstanding data when a // listener attaches, and insert it into the listener with this method. - - m_broadcaster.AddInitialEventsToListener (listener_sp, available_event_types); + m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask); } // Return the event bits that were granted to the listener - return available_event_types; + return event_mask; } bool @@ -178,36 +194,63 @@ Broadcaster::BroadcasterImpl::EventTypeHasListeners (uint32_t event_type) if (m_listeners.empty()) return false; - collection::iterator pos, end = m_listeners.end(); - for (pos = m_listeners.begin(); pos != end; ++pos) - { - if (pos->second & event_type) - return true; - } - return false; + bool result = false; + ListenerIterator([this, event_type, &result](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool { + + if (curr_event_mask & event_type) + { + result = true; + return false; // Stop iterating + } + else + { + return true; // Keep iterating + } + }); + return result; } bool -Broadcaster::BroadcasterImpl::RemoveListener (lldb::ListenerSP listener_sp, uint32_t event_mask) +Broadcaster::BroadcasterImpl::RemoveListener (lldb_private::Listener *listener, uint32_t event_mask) { - Mutex::Locker locker(m_listeners_mutex); - collection::iterator pos, end = m_listeners.end(); - // See if we already have this listener, and if so, update its mask - for (pos = m_listeners.begin(); pos != end; ++pos) + if (listener) { - if (pos->first == listener_sp) + Mutex::Locker locker(m_listeners_mutex); + collection::iterator pos = m_listeners.begin(); + // See if we already have this listener, and if so, update its mask + while (pos != m_listeners.end()) { - // Relinquish all event bits in "event_mask" - pos->second &= ~event_mask; - // If all bits have been relinquished then remove this listener - if (pos->second == 0) - m_listeners.erase (pos); - return true; + lldb::ListenerSP curr_listener_sp(pos->first.lock()); + if (curr_listener_sp) + { + if (curr_listener_sp.get() == listener) + { + // Relinquish all event bits in "event_mask" + pos->second &= ~event_mask; + // If all bits have been relinquished then remove this listener + if (pos->second == 0) + m_listeners.erase (pos); + return true; + } + ++pos; + } + else + { + // The listener has been destroyed since we couldn't turn the std::weak_ptr + // into a valid shared pointer, so we can remove it. + pos = m_listeners.erase (pos); + } } } return false; } +bool +Broadcaster::BroadcasterImpl::RemoveListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask) +{ + return RemoveListener (listener_sp.get(), event_mask); +} + void Broadcaster::BroadcasterImpl::BroadcastEvent (EventSP &event_sp) { @@ -232,7 +275,7 @@ Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool uni const uint32_t event_type = event_sp->GetType(); - Mutex::Locker event_types_locker(m_listeners_mutex); + Mutex::Locker locker(m_listeners_mutex); ListenerSP hijacking_listener_sp; @@ -263,20 +306,16 @@ Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool uni } else { - collection::iterator pos, end = m_listeners.end(); - // Iterate through all listener/mask pairs - for (pos = m_listeners.begin(); pos != end; ++pos) - { - // If the listener's mask matches any bits that we just set, then - // put the new event on its event queue. - if (event_type & pos->second) + ListenerIterator([this, unique, event_type, &event_sp](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool { + + if (event_type & curr_event_mask) { - if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type)) - continue; - pos->first->AddEvent (event_sp); + if (!unique || curr_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type) == nullptr) + curr_listener_sp->AddEvent (event_sp); } - } + return true; // Keep iterating + }); } } @@ -288,6 +327,13 @@ Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, EventData *ev } void +Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, const lldb::EventDataSP &event_data_sp) +{ + EventSP event_sp (new Event (event_type, event_data_sp)); + PrivateBroadcastEvent (event_sp, false); +} + +void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data) { EventSP event_sp (new Event (event_type, event_data)); @@ -295,9 +341,9 @@ Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, Event } bool -Broadcaster::BroadcasterImpl::HijackBroadcaster (ListenerSP listener_sp, uint32_t event_mask) +Broadcaster::BroadcasterImpl::HijackBroadcaster (const lldb::ListenerSP &listener_sp, uint32_t event_mask) { - Mutex::Locker event_types_locker(m_listeners_mutex); + Mutex::Locker locker(m_listeners_mutex); Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS)); if (log) @@ -312,7 +358,7 @@ Broadcaster::BroadcasterImpl::HijackBroadcaster (ListenerSP listener_sp, uint32_ bool Broadcaster::BroadcasterImpl::IsHijackedForEvent (uint32_t event_mask) { - Mutex::Locker event_types_locker(m_listeners_mutex); + Mutex::Locker locker(m_listeners_mutex); if (!m_hijacking_listeners.empty()) return (event_mask & m_hijacking_masks.back()) != 0; @@ -335,7 +381,7 @@ Broadcaster::BroadcasterImpl::GetHijackingListenerName() void Broadcaster::BroadcasterImpl::RestoreBroadcaster () { - Mutex::Locker event_types_locker(m_listeners_mutex); + Mutex::Locker locker(m_listeners_mutex); if (!m_hijacking_listeners.empty()) { @@ -391,7 +437,7 @@ BroadcasterManager::MakeBroadcasterManager() } uint32_t -BroadcasterManager::RegisterListenerForEvents (ListenerSP listener_sp, BroadcastEventSpec event_spec) +BroadcasterManager::RegisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { Mutex::Locker locker(m_manager_mutex); @@ -415,7 +461,7 @@ BroadcasterManager::RegisterListenerForEvents (ListenerSP listener_sp, Broadcast } bool -BroadcasterManager::UnregisterListenerForEvents (ListenerSP listener_sp, BroadcastEventSpec event_spec) +BroadcasterManager::UnregisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { Mutex::Locker locker(m_manager_mutex); bool removed_some = false; @@ -495,7 +541,7 @@ BroadcasterManager::RemoveListener(Listener *listener) } void -BroadcasterManager::RemoveListener (ListenerSP listener_sp) +BroadcasterManager::RemoveListener (const lldb::ListenerSP &listener_sp) { Mutex::Locker locker(m_manager_mutex); ListenerMatches predicate (listener_sp); diff --git a/lldb/source/Core/Event.cpp b/lldb/source/Core/Event.cpp index a8063bfb34d..6b07e4d9198 100644 --- a/lldb/source/Core/Event.cpp +++ b/lldb/source/Core/Event.cpp @@ -26,15 +26,30 @@ using namespace lldb; using namespace lldb_private; Event::Event (Broadcaster *broadcaster, uint32_t event_type, EventData *data) : - m_broadcaster_wp (broadcaster->GetBroadcasterImpl()), - m_type (event_type), - m_data_ap (data) + m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), + m_type(event_type), + m_data_sp(data) +{ +} + +Event::Event (Broadcaster *broadcaster, uint32_t event_type, const EventDataSP &event_data_sp) : + m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), + m_type(event_type), + m_data_sp(event_data_sp) { } Event::Event(uint32_t event_type, EventData *data) : - m_type (event_type), - m_data_ap (data) + m_broadcaster_wp(), + m_type(event_type), + m_data_sp(data) +{ +} + +Event::Event(uint32_t event_type, const EventDataSP &event_data_sp) : + m_broadcaster_wp(), + m_type(event_type), + m_data_sp(event_data_sp) { } @@ -69,10 +84,10 @@ Event::Dump (Stream *s) const s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ", static_cast<const void*>(this), m_type); - if (m_data_ap) + if (m_data_sp) { s->PutChar('{'); - m_data_ap->Dump (s); + m_data_sp->Dump (s); s->PutChar('}'); } else @@ -82,8 +97,8 @@ Event::Dump (Stream *s) const void Event::DoOnRemoval () { - if (m_data_ap) - m_data_ap->DoOnRemoval (this); + if (m_data_sp) + m_data_sp->DoOnRemoval (this); } EventData::EventData() = default; diff --git a/lldb/source/Core/Listener.cpp b/lldb/source/Core/Listener.cpp index e8cf39e0676..32ca1f0cebb 100644 --- a/lldb/source/Core/Listener.cpp +++ b/lldb/source/Core/Listener.cpp @@ -45,8 +45,7 @@ Listener::Listener(const char *name) : m_broadcasters(), m_broadcasters_mutex (Mutex::eMutexTypeRecursive), m_events (), - m_events_mutex (Mutex::eMutexTypeRecursive), - m_cond_wait() + m_events_mutex (Mutex::eMutexTypeNormal) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log != nullptr) @@ -74,11 +73,10 @@ Listener::Clear() { Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock()); if (broadcaster_sp) - broadcaster_sp->RemoveListener (this->shared_from_this(), pos->second.event_mask); + broadcaster_sp->RemoveListener (this, pos->second.event_mask); } m_broadcasters.clear(); - m_cond_wait.SetValue (false, eBroadcastNever); - m_broadcasters.clear(); + Mutex::Locker event_locker(m_events_mutex); m_events.clear(); size_t num_managers = m_broadcaster_managers.size(); @@ -193,9 +191,6 @@ Listener::BroadcasterWillDestruct (Broadcaster *broadcaster) else ++pos; } - - if (m_events.empty()) - m_cond_wait.SetValue (false, eBroadcastNever); } } @@ -221,12 +216,9 @@ Listener::AddEvent (EventSP &event_sp) static_cast<void*>(this), m_name.c_str(), static_cast<void*>(event_sp.get())); - // Scope for "locker" - { - Mutex::Locker locker(m_events_mutex); - m_events.push_back (event_sp); - } - m_cond_wait.SetValue (true, eBroadcastAlways); + Mutex::Locker locker(m_events_mutex); + m_events.push_back (event_sp); + m_events_condition.Broadcast(); } class EventBroadcasterMatches @@ -293,6 +285,7 @@ private: bool Listener::FindNextEventInternal ( + Mutex::Locker& lock, Broadcaster *broadcaster, // nullptr for any broadcaster const ConstString *broadcaster_names, // nullptr for any event uint32_t num_broadcaster_names, @@ -300,10 +293,10 @@ Listener::FindNextEventInternal EventSP &event_sp, bool remove) { + // NOTE: callers of this function must lock m_events_mutex using a Mutex::Locker + // and pass the locker as the first argument. m_events_mutex is no longer recursive. Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); - Mutex::Locker lock(m_events_mutex); - if (m_events.empty()) return false; @@ -333,20 +326,12 @@ Listener::FindNextEventInternal if (remove) { m_events.erase(pos); - - if (m_events.empty()) - m_cond_wait.SetValue (false, eBroadcastNever); - } - - // Unlock the event queue here. We've removed this event and are about to return - // it so it should be okay to get the next event off the queue here - and it might - // be useful to do that in the "DoOnRemoval". - lock.Unlock(); - - // Don't call DoOnRemoval if you aren't removing the event... - if (remove) + // Unlock the event queue here. We've removed this event and are about to return + // it so it should be okay to get the next event off the queue here - and it might + // be useful to do that in the "DoOnRemoval". + lock.Unlock(); event_sp->DoOnRemoval(); - + } return true; } @@ -357,8 +342,9 @@ Listener::FindNextEventInternal Event * Listener::PeekAtNextEvent () { + Mutex::Locker lock(m_events_mutex); EventSP event_sp; - if (FindNextEventInternal(nullptr, nullptr, 0, 0, event_sp, false)) + if (FindNextEventInternal(lock, nullptr, nullptr, 0, 0, event_sp, false)) return event_sp.get(); return nullptr; } @@ -366,8 +352,9 @@ Listener::PeekAtNextEvent () Event * Listener::PeekAtNextEventForBroadcaster (Broadcaster *broadcaster) { + Mutex::Locker lock(m_events_mutex); EventSP event_sp; - if (FindNextEventInternal(broadcaster, nullptr, 0, 0, event_sp, false)) + if (FindNextEventInternal(lock, broadcaster, nullptr, 0, 0, event_sp, false)) return event_sp.get(); return nullptr; } @@ -375,8 +362,9 @@ Listener::PeekAtNextEventForBroadcaster (Broadcaster *broadcaster) Event * Listener::PeekAtNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask) { + Mutex::Locker lock(m_events_mutex); EventSP event_sp; - if (FindNextEventInternal(broadcaster, nullptr, 0, event_type_mask, event_sp, false)) + if (FindNextEventInternal(lock, broadcaster, nullptr, 0, event_type_mask, event_sp, false)) return event_sp.get(); return nullptr; } @@ -388,7 +376,8 @@ Listener::GetNextEventInternal(Broadcaster *broadcaster, // nullptr uint32_t event_type_mask, EventSP &event_sp) { - return FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true); + Mutex::Locker lock(m_events_mutex); + return FindNextEventInternal (lock, broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true); } bool @@ -418,52 +407,40 @@ Listener::WaitForEventsInternal(const TimeValue *timeout, EventSP &event_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); - bool timed_out = false; - if (log != nullptr) log->Printf ("%p Listener::WaitForEventsInternal (timeout = { %p }) for %s", static_cast<void*>(this), static_cast<const void*>(timeout), m_name.c_str()); + Mutex::Locker lock(m_events_mutex); + while (true) { - // Note, we don't want to lock the m_events_mutex in the call to GetNextEventInternal, since the DoOnRemoval - // code might require that new events be serviced. For instance, the Breakpoint Command's - if (GetNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp)) - return true; - - { - // Reset condition value to false, so we can wait for new events to be - // added that might meet our current filter - // But first poll for any new event that might satisfy our condition, and if so consume it, - // otherwise wait. - - Mutex::Locker event_locker(m_events_mutex); - const bool remove = false; - if (FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, remove)) - continue; - else - m_cond_wait.SetValue (false, eBroadcastNever); - } - - if (m_cond_wait.WaitForValueEqualTo (true, timeout, &timed_out)) - continue; - - else if (timed_out) + if (FindNextEventInternal (lock, broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true)) { - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS); - if (log != nullptr) - log->Printf ("%p Listener::WaitForEventsInternal() timed out for %s", - static_cast<void*>(this), m_name.c_str()); - break; + return true; } else { - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS); - if (log != nullptr) - log->Printf ("%p Listener::WaitForEventsInternal() unknown error for %s", - static_cast<void*>(this), m_name.c_str()); - break; + bool timed_out = false; + if (m_events_condition.Wait(m_events_mutex, timeout, &timed_out) != 0) + { + if (timed_out) + { + log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS); + if (log != nullptr) + log->Printf ("%p Listener::WaitForEventsInternal() timed out for %s", + static_cast<void*>(this), m_name.c_str()); + } + else + { + log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS); + if (log != nullptr) + log->Printf ("%p Listener::WaitForEventsInternal() unknown error for %s", + static_cast<void*>(this), m_name.c_str()); + } + return false; + } } } diff --git a/lldb/source/Host/posix/HostThreadPosix.cpp b/lldb/source/Host/posix/HostThreadPosix.cpp index 9c489243193..3ac83ac07b1 100644 --- a/lldb/source/Host/posix/HostThreadPosix.cpp +++ b/lldb/source/Host/posix/HostThreadPosix.cpp @@ -53,13 +53,16 @@ Error HostThreadPosix::Cancel() { Error error; + if (IsJoinable()) + { #ifndef __ANDROID__ - int err = ::pthread_cancel(m_thread); - error.SetError(err, eErrorTypePOSIX); + assert(false && "someone is calling HostThread::Cancel()"); + int err = ::pthread_cancel(m_thread); + error.SetError(err, eErrorTypePOSIX); #else - error.SetErrorString("HostThreadPosix::Cancel() not supported on Android"); + error.SetErrorString("HostThreadPosix::Cancel() not supported on Android"); #endif - + } return error; } @@ -67,8 +70,11 @@ Error HostThreadPosix::Detach() { Error error; - int err = ::pthread_detach(m_thread); - error.SetError(err, eErrorTypePOSIX); + if (IsJoinable()) + { + int err = ::pthread_detach(m_thread); + error.SetError(err, eErrorTypePOSIX); + } Reset(); return error; } diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index f156d086d28..a880782663a 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -726,7 +726,6 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, const UnixSig m_private_state_broadcaster(nullptr, "lldb.process.internal_state_broadcaster"), m_private_state_control_broadcaster(nullptr, "lldb.process.internal_state_control_broadcaster"), m_private_state_listener_sp (Listener::MakeListener("lldb.process.internal_state_listener")), - m_private_state_control_wait(), m_mod_id (), m_process_unique_id(0), m_thread_index_id (0), @@ -4109,44 +4108,46 @@ Process::ControlPrivateStateThread (uint32_t signal) // Signal the private state thread. First we should copy this is case the // thread starts exiting since the private state thread will NULL this out // when it exits - HostThread private_state_thread(m_private_state_thread); - if (private_state_thread.IsJoinable()) { - TimeValue timeout_time; - bool timed_out; - - m_private_state_control_broadcaster.BroadcastEvent(signal, nullptr); - - timeout_time = TimeValue::Now(); - timeout_time.OffsetWithSeconds(2); - if (log) - log->Printf ("Sending control event of type: %d.", signal); - m_private_state_control_wait.WaitForValueEqualTo (true, &timeout_time, &timed_out); - m_private_state_control_wait.SetValue (false, eBroadcastNever); - - if (signal == eBroadcastInternalStateControlStop) + HostThread private_state_thread(m_private_state_thread); + if (private_state_thread.IsJoinable()) { - if (timed_out) + if (log) + log->Printf ("Sending control event of type: %d.", signal); + // Send the control event and wait for the receipt or for the private state + // thread to exit + std::shared_ptr<EventDataReceipt> event_receipt_sp(new EventDataReceipt()); + m_private_state_control_broadcaster.BroadcastEvent(signal, event_receipt_sp); + + bool receipt_received = false; + while (!receipt_received) { - Error error = private_state_thread.Cancel(); - if (log) - log->Printf ("Timed out responding to the control event, cancel got error: \"%s\".", error.AsCString()); + bool timed_out = false; + TimeValue timeout_time; + timeout_time = TimeValue::Now(); + timeout_time.OffsetWithSeconds(2); + // Check for a receipt for 2 seconds and then check if the private state + // thread is still around. + receipt_received = event_receipt_sp->WaitForEventReceived (&timeout_time, &timed_out); + if (!receipt_received) + { + // Check if the private state thread is still around. If it isn't then we are done waiting + if (!m_private_state_thread.IsJoinable()) + break; // Private state thread exited, we are done + } } - else + + if (signal == eBroadcastInternalStateControlStop) { - if (log) - log->Printf ("The control event killed the private state thread without having to cancel."); + thread_result_t result = NULL; + private_state_thread.Join(&result); } - - thread_result_t result = NULL; - private_state_thread.Join(&result); - m_private_state_thread.Reset(); } - } - else - { - if (log) - log->Printf ("Private state thread already dead, no need to signal it to stop."); + else + { + if (log) + log->Printf ("Private state thread already dead, no need to signal it to stop."); + } } } @@ -4311,7 +4312,6 @@ thread_result_t Process::RunPrivateStateThread (bool is_secondary_thread) { bool control_only = true; - m_private_state_control_wait.SetValue (false, eBroadcastNever); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); if (log) @@ -4346,7 +4346,6 @@ Process::RunPrivateStateThread (bool is_secondary_thread) break; } - m_private_state_control_wait.SetValue (true, eBroadcastAlways); continue; } else if (event_sp->GetType() == eBroadcastBitInterrupt) @@ -4442,7 +4441,6 @@ Process::RunPrivateStateThread (bool is_secondary_thread) // try to change it on the way out. if (!is_secondary_thread) m_public_run_lock.SetStopped(); - m_private_state_control_wait.SetValue (true, eBroadcastAlways); m_private_state_thread.Reset(); return NULL; } |