[Lldb-commits] [lldb] r227924 - Modify ThreadStateCoodrinator in order to resume threads if stop wasn't requested.

Chaoren Lin chaorenl at google.com
Mon Feb 2 17:51:15 PST 2015


Author: chaoren
Date: Mon Feb  2 19:51:15 2015
New Revision: 227924

URL: http://llvm.org/viewvc/llvm-project?rev=227924&view=rev
Log:
Modify ThreadStateCoodrinator in order to resume threads if stop wasn't requested.

Modified:
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
    lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
    lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h
    lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Mon Feb  2 19:51:15 2015
@@ -166,7 +166,7 @@ namespace
     {
         Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
         if (log)
-            log->Printf ("NativePlatformLinux::%s %s", __FUNCTION__, error_message.c_str ());
+            log->Printf ("NativeProcessLinux::%s %s", __FUNCTION__, error_message.c_str ());
         assert (false && "ThreadStateCoordinator error reported");
     }
 
@@ -1952,7 +1952,7 @@ NativeProcessLinux::MonitorCallback(void
     if (exited)
     {
         if (log)
-            log->Printf ("NativeProcessLinux::%s() got exit signal, tid = %"  PRIu64 " (%s main thread)", __FUNCTION__, pid, is_main_thread ? "is" : "is not");
+            log->Printf ("NativeProcessLinux::%s() got exit signal(%d) , tid = %"  PRIu64 " (%s main thread)", __FUNCTION__, signal, pid, is_main_thread ? "is" : "is not");
 
         // This is a thread that exited.  Ensure we're not tracking it anymore.
         const bool thread_found = process->StopTrackingThread (pid);
@@ -2111,7 +2111,7 @@ NativeProcessLinux::MonitorSIGTRAP(const
                 // We can now resume the newly created thread since it is fully created.
                 NotifyThreadCreateStopped (tid);
                 m_coordinator_up->RequestThreadResume (tid,
-                                                       [=](lldb::tid_t tid_to_resume)
+                                                       [=](lldb::tid_t tid_to_resume, bool supress_signal)
                                                        {
                                                            reinterpret_cast<NativeThreadLinux*> (new_thread_sp.get ())->SetRunning ();
                                                            Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
@@ -2133,7 +2133,7 @@ NativeProcessLinux::MonitorSIGTRAP(const
 
         // In all cases, we can resume the main thread here.
         m_coordinator_up->RequestThreadResume (pid,
-                                               [=](lldb::tid_t tid_to_resume)
+                                               [=](lldb::tid_t tid_to_resume, bool supress_signal)
                                                {
                                                    reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
                                                    Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
@@ -2237,10 +2237,10 @@ NativeProcessLinux::MonitorSIGTRAP(const
 
         const int signo = static_cast<int> (data);
         m_coordinator_up->RequestThreadResume (pid,
-                                               [=](lldb::tid_t tid_to_resume)
+                                               [=](lldb::tid_t tid_to_resume, bool supress_signal)
                                                {
                                                    reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
-                                                   Resume (tid_to_resume, signo);
+                                                   Resume (tid_to_resume, (supress_signal) ? LLDB_INVALID_SIGNAL_NUMBER : signo);
                                                },
                                                CoordinatorErrorHandler);
 
@@ -2253,6 +2253,11 @@ NativeProcessLinux::MonitorSIGTRAP(const
         if (log)
             log->Printf ("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 " (single stepping)", __FUNCTION__, pid);
 
+        if (thread_sp)
+        {
+            reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (SIGTRAP);
+        }
+
         // This thread is currently stopped.
         NotifyThreadStop (pid);
 
@@ -2260,6 +2265,9 @@ NativeProcessLinux::MonitorSIGTRAP(const
         // This would have already happened at the time the Resume() with step operation was signaled.
         // At this point, we just need to say we stopped, and the deferred notifcation will fire off
         // once all running threads have checked in as stopped.
+        SetCurrentThreadID (pid);
+        // Tell the process we have a stop (from software breakpoint).
+        SetState (StateType::eStateStopped, true);
         break;
 
     case SI_KERNEL:
@@ -2338,7 +2346,7 @@ NativeProcessLinux::MonitorSIGTRAP(const
             
         // Ignore these signals until we know more about them.
         m_coordinator_up->RequestThreadResume (pid,
-                                               [=](lldb::tid_t tid_to_resume)
+                                               [=](lldb::tid_t tid_to_resume, bool supress_signal)
                                                {
                                                    reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
                                                    Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
@@ -2418,7 +2426,7 @@ NativeProcessLinux::MonitorSignal(const
             // We can now resume the newly created thread since it is fully created.
             NotifyThreadCreateStopped (pid);
             m_coordinator_up->RequestThreadResume (pid,
-                                                   [=](lldb::tid_t tid_to_resume)
+                                                   [=](lldb::tid_t tid_to_resume, bool supress_signal)
                                                    {
                                                        reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
                                                        Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
@@ -2463,8 +2471,9 @@ NativeProcessLinux::MonitorSignal(const
                 // 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);
+                linux_thread_p->SetStoppedBySignal (0);
                 SetCurrentThreadID (thread_sp->GetID ());
+                m_coordinator_up->NotifyThreadStop (thread_sp->GetID (), true, CoordinatorErrorHandler);
             }
             else
             {
@@ -2485,10 +2494,9 @@ NativeProcessLinux::MonitorSignal(const
                                  stop_signo,
                                  signal_name);
                 }
+                // Tell the thread state coordinator about the stop.
+                NotifyThreadStop (thread_sp->GetID ());
             }
-
-            // Tell the thread state coordinator about the stop.
-            NotifyThreadStop (thread_sp->GetID ());
         }
 
         // Done handling.
@@ -2498,55 +2506,13 @@ NativeProcessLinux::MonitorSignal(const
     if (log)
         log->Printf ("NativeProcessLinux::%s() received signal %s", __FUNCTION__, GetUnixSignals ().GetSignalAsCString (signo));
 
+    // This thread is stopped.
+    NotifyThreadStop (pid);
+
     switch (signo)
     {
-    case SIGSEGV:
-    case SIGABRT:
-    case SIGILL:
-    case SIGFPE:
-    case SIGBUS:
-    default:
-        {
-            // This thread is stopped.
-            NotifyThreadStop (pid);
-
-            // lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
-
-            // This is just a pre-signal-delivery notification of the incoming signal.
-            if (thread_sp)
-                reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (signo);
-
-            // We can get more details on the exact nature of the crash here.
-            // ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info);
-            if (!exited)
-            {
-                // Send a stop to the debugger after we get all other threads to stop.
-                CallAfterRunningThreadsStop (pid,
-                                             [=] (lldb::tid_t signaling_tid)
-                                             {
-                                                 SetCurrentThreadID (signaling_tid);
-                                                 SetState (StateType::eStateStopped, true);
-                                             });
-            }
-            else
-            {
-                // FIXME the process might die right after this - might not ever get stops on any other threads.
-                // Send a stop to the debugger after we get all other threads to stop.
-                CallAfterRunningThreadsStop (pid,
-                                             [=] (lldb::tid_t signaling_tid)
-                                             {
-                                                 SetCurrentThreadID (signaling_tid);
-                                                 SetState (StateType::eStateCrashed, true);
-                                             });
-            }
-        }
-        break;
-
     case SIGSTOP:
         {
-            // This thread is stopped.
-            NotifyThreadStop (pid);
-
             if (log)
             {
                 if (is_from_llgs)
@@ -2558,25 +2524,38 @@ NativeProcessLinux::MonitorSignal(const
             // Resume this thread to get the group-stop mechanism to fire off the true group stops.
             // This thread will get stopped again as part of the group-stop completion.
             m_coordinator_up->RequestThreadResume (pid,
-                                                   [=](lldb::tid_t tid_to_resume)
+                                                   [=](lldb::tid_t tid_to_resume, bool supress_signal)
                                                    {
                                                        reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
                                                        // Pass this signal number on to the inferior to handle.
-                                                       Resume (tid_to_resume, signo);
+                                                       Resume (tid_to_resume, (supress_signal) ? LLDB_INVALID_SIGNAL_NUMBER : signo);
                                                    },
                                                    CoordinatorErrorHandler);
-
-            // And now we want to signal that we received a SIGSTOP on this thread
-            // as soon as all running threads stop (i.e. the group stop sequence completes).
-            CallAfterRunningThreadsStop (pid,
-                                         [=] (lldb::tid_t signaling_tid)
-                                         {
-                                             SetCurrentThreadID (signaling_tid);
-                                             SetState (StateType::eStateStopped, true);
-                                         });
         }
         break;
+    case SIGSEGV:
+    case SIGILL:
+    case SIGFPE:
+    case SIGBUS:
+        if (thread_sp)
+            reinterpret_cast<NativeThreadLinux*>(thread_sp.get())->SetCrashedWithException(
+                signo, reinterpret_cast<lldb::addr_t>(info->si_addr));
+        break;
+    default:
+        // This is just a pre-signal-delivery notification of the incoming signal.
+        if (thread_sp)
+            reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (signo);
+
+        break;
     }
+
+    // Send a stop to the debugger after we get all other threads to stop.
+    CallAfterRunningThreadsStop (pid,
+                                 [=] (lldb::tid_t signaling_tid)
+                                 {
+                                     SetCurrentThreadID (signaling_tid);
+                                     SetState (StateType::eStateStopped, true);
+                                 });
 }
 
 Error
@@ -2593,6 +2572,7 @@ NativeProcessLinux::Resume (const Resume
     int deferred_signo = 0;
     NativeThreadProtocolSP deferred_signal_thread_sp;
     int resume_count = 0;
+    bool stepping = false;
 
 
     // std::vector<NativeThreadProtocolSP> new_stop_threads;
@@ -2620,11 +2600,11 @@ NativeProcessLinux::Resume (const Resume
                 // Run the thread, possibly feeding it the signal.
                 const int signo = action->signal;
                 m_coordinator_up->RequestThreadResumeAsNeeded (thread_sp->GetID (),
-                                                               [=](lldb::tid_t tid_to_resume)
+                                                               [=](lldb::tid_t tid_to_resume, bool supress_signal)
                                                                {
                                                                    reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
                                                                    // Pass this signal number on to the inferior to handle.
-                                                                   Resume (tid_to_resume, (signo > 0) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
+                                                                   Resume (tid_to_resume, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
                                                                },
                                                                CoordinatorErrorHandler);
                 ++resume_count;
@@ -2636,31 +2616,14 @@ NativeProcessLinux::Resume (const Resume
                 // Request the step.
                 const int signo = action->signal;
                 m_coordinator_up->RequestThreadResume (thread_sp->GetID (),
-                                                       [=](lldb::tid_t tid_to_step)
+                                                       [=](lldb::tid_t tid_to_step, bool supress_signal)
                                                        {
                                                            reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStepping ();
-                                                           auto step_result = SingleStep (tid_to_step,(signo > 0) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
+                                                           auto step_result = SingleStep (tid_to_step,(signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
                                                            assert (step_result && "SingleStep() failed");
                                                        },
                                                        CoordinatorErrorHandler);
-
-                // The deferred signal tid is the stepping tid.
-                // This assumes there is only one stepping tid, or the last stepping tid is a fine choice.
-                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;
+                stepping = true;
                 break;
             }
 
@@ -2684,7 +2647,8 @@ NativeProcessLinux::Resume (const Resume
 
     // 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)
+    // If there is a stepping thread involved we'll be eventually stopped by SIGTRAP trace signal.
+    if (deferred_signal_tid != LLDB_INVALID_THREAD_ID && !stepping)
     {
         CallAfterRunningThreadsStopWithSkipTID (deferred_signal_tid,
                                                 deferred_signal_skip_tid,
@@ -3894,18 +3858,22 @@ NativeProcessLinux::NotifyThreadDeath (l
 void
 NativeProcessLinux::NotifyThreadStop (lldb::tid_t tid)
 {
-    m_coordinator_up->NotifyThreadStop (tid, CoordinatorErrorHandler);
+    m_coordinator_up->NotifyThreadStop (tid, false, CoordinatorErrorHandler);
 }
 
 void
 NativeProcessLinux::CallAfterRunningThreadsStop (lldb::tid_t tid,
                                                  const std::function<void (lldb::tid_t tid)> &call_after_function)
 {
+    Log *const log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+    if (log)
+        log->Printf("NativeProcessLinux::%s tid %" PRIu64, __FUNCTION__, tid);
+
     const lldb::pid_t pid = GetID ();
     m_coordinator_up->CallAfterRunningThreadsStop (tid,
                                                    [=](lldb::tid_t request_stop_tid)
                                                    {
-                                                       tgkill (pid, request_stop_tid, SIGSTOP);
+                                                       RequestThreadStop(pid, request_stop_tid);
                                                    },
                                                    call_after_function,
                                                    CoordinatorErrorHandler);
@@ -3916,13 +3884,36 @@ NativeProcessLinux::CallAfterRunningThre
                                                             lldb::tid_t skip_stop_request_tid,
                                                             const std::function<void (lldb::tid_t tid)> &call_after_function)
 {
+    Log *const log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+    if (log)
+        log->Printf("NativeProcessLinux::%s deferred_signal_tid %" PRIu64 ", skip_stop_request_tid %" PRIu64, __FUNCTION__, deferred_signal_tid, skip_stop_request_tid);
+
     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);
+                                                                   RequestThreadStop(pid, request_stop_tid);
                                                                },
                                                                call_after_function,
                                                                CoordinatorErrorHandler);
 }
+
+lldb_private::Error
+NativeProcessLinux::RequestThreadStop (const lldb::pid_t pid, const lldb::tid_t tid)
+{
+    Log* log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+    if (log)
+        log->Printf ("NativeProcessLinux::%s requesting thread stop(pid: %" PRIu64 ", tid: %" PRIu64 ")", __FUNCTION__, pid, tid);
+
+    Error err;
+    errno = 0;
+    if (::tgkill (pid, tid, SIGSTOP) != 0)
+    {
+        err.SetErrorToErrno ();
+        if (log)
+            log->Printf ("NativeProcessLinux::%s tgkill(%" PRIu64 ", %" PRIu64 ", SIGSTOP) failed: %s", __FUNCTION__, pid, tid, err.AsCString ());
+    }
+
+    return err;
+}

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h Mon Feb  2 19:51:15 2015
@@ -408,6 +408,9 @@ namespace lldb_private
 
         lldb_private::Error
         Detach(lldb::tid_t tid);
+
+        lldb_private::Error
+        RequestThreadStop (const lldb::pid_t pid, const lldb::tid_t tid);
     };
 } // End lldb_private namespace.
 

Modified: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp Mon Feb  2 19:51:15 2015
@@ -149,7 +149,7 @@ public:
     ProcessEvent(ThreadStateCoordinator &coordinator) override
     {
         // Validate we know about the deferred trigger thread.
-        if (coordinator.m_tid_stop_map.find (m_triggering_tid) == coordinator.m_tid_stop_map.end ())
+        if (!coordinator.IsKnownThread (m_triggering_tid))
         {
             // We don't know about this thread.  This is an error condition.
             std::ostringstream error_message;
@@ -172,7 +172,7 @@ public:
 
         if (m_wait_for_stop_tids.empty ())
         {
-        // We're not waiting for any threads.  Fire off the deferred signal delivery event.
+            // We're not waiting for any threads.  Fire off the deferred signal delivery event.
             NotifyNow ();
         }
         else
@@ -235,7 +235,7 @@ private:
     }
 
     bool
-    RequestStopOnAllSpecifiedThreads (const ThreadStateCoordinator &coordinator)
+    RequestStopOnAllSpecifiedThreads (ThreadStateCoordinator &coordinator)
     {
         // Request a stop for all the thread stops that need to be stopped
         // and are not already known to be stopped.  Keep a list of all the
@@ -246,8 +246,8 @@ private:
         {
             // Validate we know about all tids for which we must first receive a stop before
             // triggering the deferred stop notification.
-            auto find_it = coordinator.m_tid_stop_map.find (tid);
-            if (find_it == coordinator.m_tid_stop_map.end ())
+            auto find_it = coordinator.m_tid_map.find (tid);
+            if (find_it == coordinator.m_tid_map.end ())
             {
                 // This is an error.  We shouldn't be asking for waiting pids that aren't known.
                 // NOTE: we may be stripping out the specification of wait tids and handle this
@@ -261,9 +261,10 @@ private:
             }
 
             // If the pending stop thread is currently running, we need to send it a stop request.
-            if (!find_it->second)
+            if (find_it->second.m_state == ThreadState::Running)
             {
                 m_request_thread_stop_function (tid);
+                RequestThreadStop (tid, find_it->second);
                 sent_tids.insert (tid);
             }
         }
@@ -278,17 +279,17 @@ private:
     }
 
     void
-    RequestStopOnAllRunningThreads (const ThreadStateCoordinator &coordinator)
+    RequestStopOnAllRunningThreads (ThreadStateCoordinator &coordinator)
     {
         // Request a stop for all the thread stops that need to be stopped
         // and are not already known to be stopped.  Keep a list of all the
         // threads from which we still need to hear a stop reply.
 
         ThreadIDSet sent_tids;
-        for (auto it = coordinator.m_tid_stop_map.begin(); it != coordinator.m_tid_stop_map.end(); ++it)
+        for (auto it = coordinator.m_tid_map.begin(); it != coordinator.m_tid_map.end(); ++it)
         {
             // We only care about threads not stopped.
-            const bool running = !it->second;
+            const bool running = it->second.m_state == ThreadState::Running;
             if (running)
             {
                 const lldb::tid_t tid = it->first;
@@ -296,7 +297,7 @@ private:
                 // Request this thread stop if the tid stop request is not explicitly ignored.
                 const bool skip_stop_request = m_skip_stop_request_tids.count (tid) > 0;
                 if (!skip_stop_request)
-                    m_request_thread_stop_function (tid);
+                    RequestThreadStop (tid, it->second);
 
                 // Even if we skipped sending the stop request for other reasons (like stepping),
                 // we still need to wait for that stepping thread to notify completion/stop.
@@ -308,6 +309,13 @@ private:
         m_wait_for_stop_tids.swap (sent_tids);
     }
 
+    void
+    RequestThreadStop (lldb::tid_t tid, ThreadContext& context)
+    {
+        m_request_thread_stop_function (tid);
+        context.m_stop_requested = true;
+    }
+
     const lldb::tid_t m_triggering_tid;
     ThreadIDSet m_wait_for_stop_tids;
     const ThreadIDSet m_original_wait_for_stop_tids;
@@ -348,9 +356,11 @@ class ThreadStateCoordinator::EventThrea
 {
 public:
     EventThreadStopped (lldb::tid_t tid,
+                        bool initiated_by_llgs,
                         const ErrorFunction &error_function):
     EventBase (),
     m_tid (tid),
+    m_initiated_by_llgs (initiated_by_llgs),
     m_error_function (error_function)
     {
     }
@@ -358,7 +368,7 @@ public:
     EventLoopResult
     ProcessEvent(ThreadStateCoordinator &coordinator) override
     {
-        coordinator.ThreadDidStop (m_tid, m_error_function);
+        coordinator.ThreadDidStop (m_tid, m_initiated_by_llgs, m_error_function);
         return eventLoopResultContinue;
     }
 
@@ -373,6 +383,7 @@ public:
 private:
 
     const lldb::tid_t m_tid;
+    const bool m_initiated_by_llgs;
     ErrorFunction m_error_function;
 };
 
@@ -453,7 +464,7 @@ class ThreadStateCoordinator::EventReque
 {
 public:
     EventRequestResume (lldb::tid_t tid,
-                        const ThreadIDFunction &request_thread_resume_function,
+                        const ResumeThreadFunction &request_thread_resume_function,
                         const ErrorFunction &error_function,
                         bool error_when_already_running):
     EventBase (),
@@ -468,8 +479,8 @@ public:
     ProcessEvent(ThreadStateCoordinator &coordinator) override
     {
         // Ensure we know about the thread.
-        auto find_it = coordinator.m_tid_stop_map.find (m_tid);
-        if (find_it == coordinator.m_tid_stop_map.end ())
+        auto find_it = coordinator.m_tid_map.find (m_tid);
+        if (find_it == coordinator.m_tid_map.end ())
         {
             // We don't know about this thread.  This is an error condition.
             std::ostringstream error_message;
@@ -477,9 +488,9 @@ public:
             m_error_function (error_message.str ());
             return eventLoopResultContinue;
         }
-        
+        auto& context = find_it->second;
         // Tell the thread to resume if we don't already think it is running.
-        const bool is_stopped = find_it->second;
+        const bool is_stopped = context.m_state == ThreadState::Stopped;
         if (!is_stopped)
         {
             // It's not an error, just a log, if the m_already_running_no_error flag is set.
@@ -532,10 +543,11 @@ public:
 
         // Request a resume.  We expect this to be synchronous and the system
         // to reflect it is running after this completes.
-        m_request_thread_resume_function (m_tid);
+        m_request_thread_resume_function (m_tid, false);
 
         // Now mark it is running.
-        find_it->second = false;
+        context.m_state = ThreadState::Running;
+        context.m_request_resume_function = m_request_thread_resume_function;
 
         return eventLoopResultContinue;
     }
@@ -551,7 +563,7 @@ public:
 private:
 
     const lldb::tid_t m_tid;
-    ThreadIDFunction m_request_thread_resume_function;
+    ResumeThreadFunction m_request_thread_resume_function;
     ErrorFunction m_error_function;
     const bool m_error_when_already_running;
 };
@@ -563,7 +575,7 @@ ThreadStateCoordinator::ThreadStateCoord
     m_event_queue (),
     m_queue_condition (),
     m_queue_mutex (),
-    m_tid_stop_map (),
+    m_tid_map (),
     m_log_event_processing (false)
 {
 }
@@ -660,11 +672,11 @@ ThreadStateCoordinator::CallAfterRunning
 
 
 void
-ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, ErrorFunction &error_function)
+ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, ErrorFunction &error_function)
 {
     // Ensure we know about the thread.
-    auto find_it = m_tid_stop_map.find (tid);
-    if (find_it == m_tid_stop_map.end ())
+    auto find_it = m_tid_map.find (tid);
+    if (find_it == m_tid_map.end ())
     {
         // We don't know about this thread.  This is an error condition.
         std::ostringstream error_message;
@@ -674,7 +686,10 @@ ThreadStateCoordinator::ThreadDidStop (l
     }
 
     // Update the global list of known thread states.  This one is definitely stopped.
-    find_it->second = true;
+    auto& context = find_it->second;
+    const auto stop_was_requested = context.m_stop_requested;
+    context.m_state = ThreadState::Stopped;
+    context.m_stop_requested = false;
 
     // If we have a pending notification, remove this from the set.
     EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
@@ -687,14 +702,23 @@ ThreadStateCoordinator::ThreadDidStop (l
             m_pending_notification_sp.reset ();
         }
     }
+
+    if (initiated_by_llgs && context.m_request_resume_function && !stop_was_requested)
+    {
+        // We can end up here if stop was initiated by LLGS but by this time a
+        // thread stop has occurred - maybe initiated by another event.
+        Log ("Resuming thread %"  PRIu64 " since stop wasn't requested", tid);
+        context.m_request_resume_function (tid, true);
+        context.m_state = ThreadState::Running;
+    }
 }
 
 void
 ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function)
 {
     // Ensure we don't already know about the thread.
-    auto find_it = m_tid_stop_map.find (tid);
-    if (find_it != m_tid_stop_map.end ())
+    auto find_it = m_tid_map.find (tid);
+    if (find_it != m_tid_map.end ())
     {
         // We already know about this thread.  This is an error condition.
         std::ostringstream error_message;
@@ -704,7 +728,9 @@ ThreadStateCoordinator::ThreadWasCreated
     }
 
     // Add the new thread to the stop map.
-    m_tid_stop_map[tid] = is_stopped;
+    ThreadContext ctx;
+    ctx.m_state = (is_stopped) ? ThreadState::Stopped : ThreadState::Running;
+    m_tid_map[tid] = std::move(ctx);
 
     EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
     if (call_after_event && !is_stopped)
@@ -719,8 +745,8 @@ void
 ThreadStateCoordinator::ThreadDidDie (lldb::tid_t tid, ErrorFunction &error_function)
 {
     // Ensure we know about the thread.
-    auto find_it = m_tid_stop_map.find (tid);
-    if (find_it == m_tid_stop_map.end ())
+    auto find_it = m_tid_map.find (tid);
+    if (find_it == m_tid_map.end ())
     {
         // We don't know about this thread.  This is an error condition.
         std::ostringstream error_message;
@@ -732,7 +758,7 @@ ThreadStateCoordinator::ThreadDidDie (ll
     // Update the global list of known thread states.  While this one is stopped, it is also dead.
     // So stop tracking it.  We assume the user of this coordinator will not keep trying to add
     // dependencies on a thread after it is known to be dead.
-    m_tid_stop_map.erase (find_it);
+    m_tid_map.erase (find_it);
 
     // If we have a pending notification, remove this from the set.
     EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
@@ -757,7 +783,7 @@ ThreadStateCoordinator::ResetNow ()
     // The caller is expected to reset thread states for all threads, and we
     // will assume anything we haven't heard about is running and requires a
     // stop.
-    m_tid_stop_map.clear ();
+    m_tid_map.clear ();
 }
 
 void
@@ -773,27 +799,26 @@ ThreadStateCoordinator::Log (const char
 
 void
 ThreadStateCoordinator::NotifyThreadStop (lldb::tid_t tid,
+                                          bool initiated_by_llgs,
                                           const ErrorFunction &error_function)
 {
-    EnqueueEvent (EventBaseSP (new EventThreadStopped (tid, error_function)));
+    EnqueueEvent (EventBaseSP (new EventThreadStopped (tid, initiated_by_llgs, error_function)));
 }
 
 void
 ThreadStateCoordinator::RequestThreadResume (lldb::tid_t tid,
-                                             const ThreadIDFunction &request_thread_resume_function,
+                                             const ResumeThreadFunction &request_thread_resume_function,
                                              const ErrorFunction &error_function)
 {
-    const bool error_when_already_running = true;
-    EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, error_when_already_running)));
+    EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, true)));
 }
 
 void
 ThreadStateCoordinator::RequestThreadResumeAsNeeded (lldb::tid_t tid,
-                                                     const ThreadIDFunction &request_thread_resume_function,
+                                                     const ResumeThreadFunction &request_thread_resume_function,
                                                      const ErrorFunction &error_function)
 {
-    const bool error_when_already_running = false;
-    EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, error_when_already_running)));
+    EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, false)));
 }
 
 void
@@ -880,3 +905,9 @@ ThreadStateCoordinator::GetPendingThread
 {
     return static_cast<EventCallAfterThreadsStop*> (m_pending_notification_sp.get ());
 }
+
+bool
+ThreadStateCoordinator::IsKnownThread (lldb::tid_t tid) const
+{
+    return m_tid_map.find (tid) != m_tid_map.end ();
+}

Modified: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h Mon Feb  2 19:51:15 2015
@@ -38,6 +38,7 @@ namespace lldb_private
         typedef std::function<void (lldb::tid_t tid)> ThreadIDFunction;
         typedef std::function<void (const char *format, va_list args)> LogFunction;
         typedef std::function<void (const std::string &error_message)> ErrorFunction;
+        typedef std::function<void (lldb::tid_t tid, bool supress_signal)> ResumeThreadFunction;
 
         // Constructors.
         ThreadStateCoordinator (const LogFunction &log_function);
@@ -98,6 +99,7 @@ namespace lldb_private
         // already think it is stopped.
         void
         NotifyThreadStop (lldb::tid_t tid,
+                          bool initiated_by_llgs,
                           const ErrorFunction &error_function);
 
         // Request that the given thread id should have the request_thread_resume_function
@@ -106,7 +108,7 @@ namespace lldb_private
         // a thread that is already in a running state.
         void
         RequestThreadResume (lldb::tid_t tid,
-                             const ThreadIDFunction &request_thread_resume_function,
+                             const ResumeThreadFunction &request_thread_resume_function,
                              const ErrorFunction &error_function);
 
         // Request that the given thread id should have the request_thread_resume_function
@@ -115,7 +117,7 @@ namespace lldb_private
         // does not trigger an error in that case.
         void
         RequestThreadResumeAsNeeded (lldb::tid_t tid,
-                                     const ThreadIDFunction &request_thread_resume_function,
+                                     const ResumeThreadFunction &request_thread_resume_function,
                                      const ErrorFunction &error_function);
 
         // Indicate the calling process did an exec and that the thread state
@@ -160,7 +162,19 @@ namespace lldb_private
 
         typedef std::queue<EventBaseSP> QueueType;
 
-        typedef std::unordered_map<lldb::tid_t, bool> TIDBoolMap;
+        enum class ThreadState
+        {
+            Running,
+            Stopped
+        };
+
+        struct ThreadContext
+        {
+            ThreadState m_state;
+            bool m_stop_requested = false;
+            ResumeThreadFunction m_request_resume_function;
+        };
+        typedef std::unordered_map<lldb::tid_t, ThreadContext> TIDContextMap;
 
 
         // Private member functions.
@@ -174,7 +188,7 @@ namespace lldb_private
         SetPendingNotification (const EventBaseSP &event_sp);
 
         void
-        ThreadDidStop (lldb::tid_t tid, ErrorFunction &error_function);
+        ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, ErrorFunction &error_function);
 
         void
         ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function);
@@ -185,6 +199,9 @@ namespace lldb_private
         void
         ResetNow ();
 
+        bool
+        IsKnownThread(lldb::tid_t tid) const;
+
         void
         Log (const char *format, ...);
 
@@ -204,8 +221,8 @@ namespace lldb_private
 
         EventBaseSP m_pending_notification_sp;
 
-        // Maps known TIDs to stop (true) or not-stopped (false) state.
-        TIDBoolMap m_tid_stop_map;
+        // Maps known TIDs to ThreadContext.
+        TIDContextMap m_tid_map;
 
         bool m_log_event_processing;
     };

Modified: lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py (original)
+++ lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py Mon Feb  2 19:51:15 2015
@@ -372,7 +372,7 @@ class ConcurrentEventsTestCase(TestBase)
         """
         return self.finish_breakpoint.GetHitCount() > 0 or \
                 self.crash_count > 0 or \
-                self.inferior_process.GetState == lldb.eStateExited
+                self.inferior_process.GetState() == lldb.eStateExited
 
     def do_thread_actions(self,
                           num_breakpoint_threads = 0,





More information about the lldb-commits mailing list