[Lldb-commits] [lldb] a913a58 - [lldb] Simplify the is_finalized logic in process and make it thread safe.
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Fri Dec 18 18:41:41 PST 2020
Author: Jonas Devlieghere
Date: 2020-12-18T18:41:33-08:00
New Revision: a913a583f00a31c37a1572089fe8898a6c19536c
URL: https://github.com/llvm/llvm-project/commit/a913a583f00a31c37a1572089fe8898a6c19536c
DIFF: https://github.com/llvm/llvm-project/commit/a913a583f00a31c37a1572089fe8898a6c19536c.diff
LOG: [lldb] Simplify the is_finalized logic in process and make it thread safe.
This is a speculative fix when looking at the finalization code in
Process. It tackles the following issues:
- Adds synchronization to prevent races between threads.
- Marks the process as finalized/invalid as soon as Finalize is called
rather than at the end.
- Simplifies the code by using only a single instance variable to track
finalization.
Differential revision: https://reviews.llvm.org/D93479
Added:
Modified:
lldb/include/lldb/Target/Process.h
lldb/source/Target/Process.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 744deab276c4..e8dd8847e87a 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -594,7 +594,7 @@ class Process : public std::enable_shared_from_this<Process>,
/// \return
/// Returns \b true if this Process has not been finalized
/// and \b false otherwise.
- bool IsValid() const { return !m_finalize_called; }
+ bool IsValid() const { return !m_finalizing; }
/// Return a multi-word command object that can be used to expose plug-in
/// specific commands.
@@ -2831,10 +2831,11 @@ void PruneThreadPlans();
// m_currently_handling_do_on_removals are true,
// Resume will only request a resume, using this
// flag to check.
- bool m_finalizing; // This is set at the beginning of Process::Finalize() to
- // stop functions from looking up or creating things
- // during a finalize call
- bool m_finalize_called; // This is set at the end of Process::Finalize()
+
+ /// This is set at the beginning of Process::Finalize() to stop functions
+ /// from looking up or creating things during or after a finalize call.
+ std::atomic<bool> m_finalizing;
+
bool m_clear_thread_plans_on_stop;
bool m_force_next_event_delivery;
lldb::StateType m_last_broadcast_state; /// This helps with the Public event
@@ -2938,6 +2939,8 @@ void PruneThreadPlans();
void LoadOperatingSystemPlugin(bool flush);
private:
+ Status DestroyImpl(bool force_kill);
+
/// This is the part of the event handling that for a process event. It
/// decides what to do with the event and returns true if the event needs to
/// be propagated to the user, and false otherwise. If the event is not
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 14f8326cfcec..a4eab1aa0b41 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -556,7 +556,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp,
m_profile_data_comm_mutex(), m_profile_data(), m_iohandler_sync(0),
m_memory_cache(*this), m_allocated_memory_cache(*this),
m_should_detach(false), m_next_event_action_up(), m_public_run_lock(),
- m_private_run_lock(), m_finalizing(false), m_finalize_called(false),
+ m_private_run_lock(), m_finalizing(false),
m_clear_thread_plans_on_stop(false), m_force_next_event_delivery(false),
m_last_broadcast_state(eStateInvalid), m_destroy_in_process(false),
m_can_interpret_function_calls(false), m_warnings_issued(),
@@ -632,7 +632,8 @@ const ProcessPropertiesSP &Process::GetGlobalProperties() {
}
void Process::Finalize() {
- m_finalizing = true;
+ if (m_finalizing.exchange(true))
+ return;
// Destroy this process if needed
switch (GetPrivateState()) {
@@ -644,7 +645,7 @@ void Process::Finalize() {
case eStateStepping:
case eStateCrashed:
case eStateSuspended:
- Destroy(false);
+ DestroyImpl(false);
break;
case eStateInvalid:
@@ -707,7 +708,6 @@ void Process::Finalize() {
m_private_run_lock.TrySetRunning(); // This will do nothing if already locked
m_private_run_lock.SetStopped();
m_structured_data_plugin_map.clear();
- m_finalize_called = true;
}
void Process::RegisterNotificationCallbacks(const Notifications &callbacks) {
@@ -1516,7 +1516,7 @@ bool Process::StateChangedIsHijackedForSynchronousResume() {
StateType Process::GetPrivateState() { return m_private_state.GetValue(); }
void Process::SetPrivateState(StateType new_state) {
- if (m_finalize_called)
+ if (m_finalizing)
return;
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STATE |
@@ -1566,11 +1566,7 @@ void Process::SetPrivateState(StateType new_state) {
StateAsCString(new_state), m_mod_id.GetStopID());
}
- // Use our target to get a shared pointer to ourselves...
- if (m_finalize_called && !PrivateStateThreadIsValid())
- BroadcastEvent(event_sp);
- else
- m_private_state_broadcaster.BroadcastEvent(event_sp);
+ m_private_state_broadcaster.BroadcastEvent(event_sp);
} else {
LLDB_LOGF(log,
"Process::SetPrivateState (%s) state didn't change. Ignoring...",
@@ -3345,9 +3341,12 @@ Status Process::Detach(bool keep_stopped) {
Status Process::Destroy(bool force_kill) {
// If we've already called Process::Finalize then there's nothing useful to
// be done here. Finalize has actually called Destroy already.
- if (m_finalize_called)
+ if (m_finalizing)
return {};
+ return DestroyImpl(force_kill);
+}
+Status Process::DestroyImpl(bool force_kill) {
// Tell ourselves we are in the process of destroying the process, so that we
// don't do any unnecessary work that might hinder the destruction. Remember
// to set this back to false when we are done. That way if the attempt
More information about the lldb-commits
mailing list