diff options
Diffstat (limited to 'lldb')
4 files changed, 101 insertions, 9 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index eaf83d1f2c2..5c297589172 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -2532,8 +2532,10 @@ NativeProcessLinux::MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool e GetID (), pid); - // An inferior thread just stopped. Mark it as such. - reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (signo); + // An inferior thread just stopped, but was not the primary cause of the process stop. + // Instead, something else (like a breakpoint or step) caused the stop. Mark the + // stop signal as 0 to let lldb know this isn't the important stop. + reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (0); SetCurrentThreadID (thread_sp->GetID ()); // Tell the thread state coordinator about the stop. @@ -2656,11 +2658,14 @@ NativeProcessLinux::Resume (const ResumeActionList &resume_actions) if (log) log->Printf ("NativeProcessLinux::%s called: pid %" PRIu64, __FUNCTION__, GetID ()); - int deferred_signal_tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t deferred_signal_tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t deferred_signal_skip_tid = LLDB_INVALID_THREAD_ID; int deferred_signo = 0; NativeThreadProtocolSP deferred_signal_thread_sp; + int resume_count = 0; - std::vector<NativeThreadProtocolSP> new_stop_threads; + + // std::vector<NativeThreadProtocolSP> new_stop_threads; // Scope for threads mutex. { @@ -2692,6 +2697,7 @@ NativeProcessLinux::Resume (const ResumeActionList &resume_actions) Resume (tid_to_resume, (signo > 0) ? signo : LLDB_INVALID_SIGNAL_NUMBER); }, CoordinatorErrorHandler); + ++resume_count; break; } @@ -2713,6 +2719,16 @@ NativeProcessLinux::Resume (const ResumeActionList &resume_actions) deferred_signal_tid = thread_sp->GetID (); deferred_signal_thread_sp = thread_sp; + // Don't send a stop request to this thread. The thread resume request + // above will actually run the step thread, and it will finish the step + // by sending a SIGTRAP with the appropriate bits set. So, the deferred + // signal call that happens at the end of the loop below needs to let + // the pending signal handling to *not* send a stop for this thread here + // since the start/stop step functionality will end up with a stop state. + // Otherwise, this stepping thread will get sent an erroneous tgkill for + // with a SIGSTOP signal. + deferred_signal_skip_tid = thread_sp->GetID (); + // And the stop signal we should apply for it is a SIGTRAP. deferred_signo = SIGTRAP; break; @@ -2736,13 +2752,17 @@ NativeProcessLinux::Resume (const ResumeActionList &resume_actions) } } - // We don't need to tell the delegate when we're running, so don't do that here. + // If we resumed anything, this command was about starting a stopped thread, + // not about stopping something that we should trigger later. + if (resume_count > 0) + return error; // If we had any thread stopping, then do a deferred notification of the chosen stop thread id and signal // after all other running threads have stopped. if (deferred_signal_tid != LLDB_INVALID_THREAD_ID) { - CallAfterRunningThreadsStop (deferred_signal_tid, + CallAfterRunningThreadsStopWithSkipTID (deferred_signal_tid, + deferred_signal_skip_tid, [=](lldb::tid_t deferred_notification_tid) { // Set the signal thread to the current thread. @@ -3904,5 +3924,20 @@ NativeProcessLinux::CallAfterRunningThreadsStop (lldb::tid_t tid, }, call_after_function, CoordinatorErrorHandler); +} +void +NativeProcessLinux::CallAfterRunningThreadsStopWithSkipTID (lldb::tid_t deferred_signal_tid, + lldb::tid_t skip_stop_request_tid, + const std::function<void (lldb::tid_t tid)> &call_after_function) +{ + const lldb::pid_t pid = GetID (); + m_coordinator_up->CallAfterRunningThreadsStopWithSkipTIDs (deferred_signal_tid, + skip_stop_request_tid != LLDB_INVALID_THREAD_ID ? ThreadStateCoordinator::ThreadIDSet {skip_stop_request_tid} : ThreadStateCoordinator::ThreadIDSet (), + [=](lldb::tid_t request_stop_tid) + { + tgkill (pid, request_stop_tid, SIGSTOP); + }, + call_after_function, + CoordinatorErrorHandler); } diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h index 93d965e6952..e75231be368 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -398,6 +398,11 @@ namespace lldb_private CallAfterRunningThreadsStop (lldb::tid_t tid, const std::function<void (lldb::tid_t tid)> &call_after_function); + void + CallAfterRunningThreadsStopWithSkipTID (lldb::tid_t deferred_signal_tid, + lldb::tid_t skip_stop_request_tid, + const std::function<void (lldb::tid_t tid)> &call_after_function); + lldb_private::Error Detach(lldb::tid_t tid); }; diff --git a/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp b/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp index e4d412e2386..09a5598da7b 100644 --- a/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp +++ b/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp @@ -83,7 +83,8 @@ public: m_request_thread_stop_function (request_thread_stop_function), m_call_after_function (call_after_function), m_error_function (error_function), - m_request_stop_on_all_unstopped_threads (false) + m_request_stop_on_all_unstopped_threads (false), + m_skip_stop_request_tids () { } @@ -98,7 +99,25 @@ public: m_request_thread_stop_function (request_thread_stop_function), m_call_after_function (call_after_function), m_error_function (error_function), - m_request_stop_on_all_unstopped_threads (true) + m_request_stop_on_all_unstopped_threads (true), + m_skip_stop_request_tids () + { + } + + EventCallAfterThreadsStop (lldb::tid_t triggering_tid, + const ThreadIDFunction &request_thread_stop_function, + const ThreadIDFunction &call_after_function, + const ThreadIDSet &skip_stop_request_tids, + const ErrorFunction &error_function) : + EventBase (), + m_triggering_tid (triggering_tid), + m_wait_for_stop_tids (), + m_original_wait_for_stop_tids (), + m_request_thread_stop_function (request_thread_stop_function), + m_call_after_function (call_after_function), + m_error_function (error_function), + m_request_stop_on_all_unstopped_threads (true), + m_skip_stop_request_tids (skip_stop_request_tids) { } @@ -203,7 +222,7 @@ public: GetDescription () override { std::ostringstream description; - description << "EventCallAfterThreadsStop (triggering_tid=" << m_triggering_tid << ", request_stop_on_all_unstopped_threads=" << m_request_stop_on_all_unstopped_threads << ")"; + description << "EventCallAfterThreadsStop (triggering_tid=" << m_triggering_tid << ", request_stop_on_all_unstopped_threads=" << m_request_stop_on_all_unstopped_threads << ", skip_stop_request_tids.size()=" << m_skip_stop_request_tids.size () << ")"; return description.str (); } @@ -268,6 +287,10 @@ private: ThreadIDSet sent_tids; for (auto it = coordinator.m_tid_stop_map.begin(); it != coordinator.m_tid_stop_map.end(); ++it) { + // Ignore threads we explicitly listed as skipped for stop requests. + if (m_skip_stop_request_tids.count (it->first) > 0) + continue; + // We only care about threads not stopped. const bool running = !it->second; if (running) @@ -290,6 +313,7 @@ private: ThreadIDFunction m_call_after_function; ErrorFunction m_error_function; const bool m_request_stop_on_all_unstopped_threads; + ThreadIDSet m_skip_stop_request_tids; }; //===----------------------------------------------------------------------===// @@ -601,6 +625,21 @@ ThreadStateCoordinator::CallAfterRunningThreadsStop (const lldb::tid_t triggerin } void +ThreadStateCoordinator::CallAfterRunningThreadsStopWithSkipTIDs (lldb::tid_t triggering_tid, + const ThreadIDSet &skip_stop_request_tids, + const ThreadIDFunction &request_thread_stop_function, + const ThreadIDFunction &call_after_function, + const ErrorFunction &error_function) +{ + EnqueueEvent (EventBaseSP (new EventCallAfterThreadsStop (triggering_tid, + request_thread_stop_function, + call_after_function, + skip_stop_request_tids, + error_function))); +} + + +void ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, ErrorFunction &error_function) { // Ensure we know about the thread. diff --git a/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.h b/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.h index 8641c14e3eb..267cfc36e3a 100644 --- a/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.h +++ b/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.h @@ -81,6 +81,19 @@ namespace lldb_private const ThreadIDFunction &call_after_function, const ErrorFunction &error_function); + // This method is the main purpose of the class: triggering a deferred + // action after all non-stopped threads stop. The triggering_tid is the + // thread id passed to the call_after_function. The error_function will + // be fired if the triggering tid is unknown at the time of execution. + // This variant will send stop requests to all non-stopped threads except + // for any contained in skip_stop_request_tids. + void + CallAfterRunningThreadsStopWithSkipTIDs (lldb::tid_t triggering_tid, + const ThreadIDSet &skip_stop_request_tids, + const ThreadIDFunction &request_thread_stop_function, + const ThreadIDFunction &call_after_function, + const ErrorFunction &error_function); + // Notify the thread stopped. Will trigger error at time of execution if we // already think it is stopped. void |