From aab58633b719c23760c39320e4792f96568fef58 Mon Sep 17 00:00:00 2001 From: Chaoren Lin Date: Tue, 3 Feb 2015 01:50:57 +0000 Subject: Added code to prevent "administrative stop" from overwriting a real stop reason. Note this code path should not happen - it implies a bug in another part of the code. For the thread to receive the stop signal as it is handled, the and for it to already have a stop reason, it implies the kernel was able to tell the thread that it stopped while it was stopped. More likely this seems to indicate a bug where an actual thread start was not getting correctly logged. If it does get hit, we'll want to understand the sequence to figure out if it is truly legitimate or if it implies another bug. llvm-svn: 227916 --- .../Plugins/Process/Linux/NativeProcessLinux.cpp | 43 +++++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp') diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 436f4e23c161..7b3d72c2c744 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -2521,11 +2521,44 @@ NativeProcessLinux::MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool e GetID (), pid); - // 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 (thread_sp.get ())->SetStoppedBySignal (0); - SetCurrentThreadID (thread_sp->GetID ()); + // Check that we're not already marked with a stop reason. + // Note this thread really shouldn't already be marked as stopped - if we were, that would imply that + // the kernel signaled us with the thread stopping which we handled and marked as stopped, + // and that, without an intervening resume, we received another stop. It is more likely + // that we are missing the marking of a run state somewhere if we find that the thread was + // marked as stopped. + NativeThreadLinux *const linux_thread_p = reinterpret_cast (thread_sp.get ()); + assert (linux_thread_p && "linux_thread_p is null!"); + + const StateType thread_state = linux_thread_p->GetState (); + if (!StateIsStoppedState (thread_state, false)) + { + // 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 (thread_sp.get ())->SetStoppedBySignal (0); + SetCurrentThreadID (thread_sp->GetID ()); + } + else + { + if (log) + { + // Retrieve the signal name if the thread was stopped by a signal. + int stop_signo = 0; + const bool stopped_by_signal = linux_thread_p->IsStopped (&stop_signo); + const char *signal_name = stopped_by_signal ? GetUnixSignals ().GetSignalAsCString (stop_signo) : ""; + if (!signal_name) + signal_name = ""; + + log->Printf ("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 ", thread was already marked as a stopped state (state=%s, signal=%d (%s)), leaving stop signal as is", + __FUNCTION__, + GetID (), + linux_thread_p->GetID (), + StateAsCString (thread_state), + stop_signo, + signal_name); + } + } // Tell the thread state coordinator about the stop. NotifyThreadStop (thread_sp->GetID ()); -- cgit v1.2.3