[Lldb-commits] [lldb] r228387 - Fix TestThreadSpecificBreakpoint with LLGS

Tamas Berghammer tberghammer at google.com
Fri Feb 6 02:42:33 PST 2015


Author: tberghammer
Date: Fri Feb  6 04:42:33 2015
New Revision: 228387

URL: http://llvm.org/viewvc/llvm-project?rev=228387&view=rev
Log:
Fix TestThreadSpecificBreakpoint with LLGS

* Set the state of the process into running/stepping on continue/step operations
* Add mutex to use transactions in Thread State Coordinator
** It is required because the events from two Signal Handler or form a Signal handler and a Resume request shouldn't overlap
* Send Stop Replay Packet only when the state of the process changed

Differential Revision: http://reviews.llvm.org/D7374

Modified:
    lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp

Modified: lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeProcessProtocol.cpp?rev=228387&r1=228386&r2=228387&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/NativeProcessProtocol.cpp (original)
+++ lldb/trunk/source/Host/common/NativeProcessProtocol.cpp Fri Feb  6 04:42:33 2015
@@ -402,6 +402,10 @@ void
 NativeProcessProtocol::SetState (lldb::StateType state, bool notify_delegates)
 {
     Mutex::Locker locker (m_state_mutex);
+
+    if (state == m_state)
+        return;
+
     m_state = state;
 
     if (StateIsStoppedState (state, false))

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=228387&r1=228386&r2=228387&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Fri Feb  6 04:42:33 2015
@@ -1497,8 +1497,6 @@ NativeProcessLinux::Launch(LaunchArgs *a
 
     NativeProcessLinux *monitor = args->m_monitor;
     assert (monitor && "monitor is NULL");
-    if (!monitor)
-        return false;
 
     const char **argv = args->m_argv;
     const char **envp = args->m_envp;
@@ -2073,6 +2071,8 @@ NativeProcessLinux::MonitorSIGTRAP(const
     if (!info)
         return;
 
+    Mutex::Locker locker (m_threads_mutex);
+
     // See if we can find a thread for this signal.
     NativeThreadProtocolSP thread_sp = GetThreadByID (pid);
     if (!thread_sp)
@@ -2158,45 +2158,41 @@ NativeProcessLinux::MonitorSIGTRAP(const
         m_coordinator_up->ResetForExec ();
 
         // Remove all but the main thread here.  Linux fork creates a new process which only copies the main thread.  Mutexes are in undefined state.
-        {
-            Mutex::Locker locker (m_threads_mutex);
-
-            if (log)
-                log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__);
-
-            for (auto thread_sp : m_threads)
-            {
-                const bool is_main_thread = thread_sp && thread_sp->GetID () == GetID ();
-                if (is_main_thread)
-                {
-                    main_thread_sp = thread_sp;
-                    if (log)
-                        log->Printf ("NativeProcessLinux::%s found main thread with tid %" PRIu64 ", keeping", __FUNCTION__, main_thread_sp->GetID ());
-                }
-                else
-                {
-                    // Tell thread coordinator this thread is dead.
-                    if (log)
-                        log->Printf ("NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64 " due to exec", __FUNCTION__, thread_sp->GetID ());
-                }
-            }
-
-            m_threads.clear ();
+        if (log)
+            log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__);
 
-            if (main_thread_sp)
+        for (auto thread_sp : m_threads)
+        {
+            const bool is_main_thread = thread_sp && thread_sp->GetID () == GetID ();
+            if (is_main_thread)
             {
-                m_threads.push_back (main_thread_sp);
-                SetCurrentThreadID (main_thread_sp->GetID ());
-                reinterpret_cast<NativeThreadLinux*>(main_thread_sp.get())->SetStoppedByExec ();
+                main_thread_sp = thread_sp;
+                if (log)
+                    log->Printf ("NativeProcessLinux::%s found main thread with tid %" PRIu64 ", keeping", __FUNCTION__, main_thread_sp->GetID ());
             }
             else
             {
-                SetCurrentThreadID (LLDB_INVALID_THREAD_ID);
+                // Tell thread coordinator this thread is dead.
                 if (log)
-                    log->Printf ("NativeProcessLinux::%s pid %" PRIu64 "no main thread found, discarded all threads, we're in a no-thread state!", __FUNCTION__, GetID ());
+                    log->Printf ("NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64 " due to exec", __FUNCTION__, thread_sp->GetID ());
             }
         }
 
+        m_threads.clear ();
+
+        if (main_thread_sp)
+        {
+            m_threads.push_back (main_thread_sp);
+            SetCurrentThreadID (main_thread_sp->GetID ());
+            reinterpret_cast<NativeThreadLinux*>(main_thread_sp.get())->SetStoppedByExec ();
+        }
+        else
+        {
+            SetCurrentThreadID (LLDB_INVALID_THREAD_ID);
+            if (log)
+                log->Printf ("NativeProcessLinux::%s pid %" PRIu64 "no main thread found, discarded all threads, we're in a no-thread state!", __FUNCTION__, GetID ());
+        }
+
         // Tell coordinator about about the "new" (since exec) stopped main thread.
         const lldb::tid_t main_thread_tid = GetID ();
         NotifyThreadCreateStopped (main_thread_tid);
@@ -2210,7 +2206,11 @@ NativeProcessLinux::MonitorSIGTRAP(const
         assert (main_thread_sp && "exec called during ptraced process but no main thread metadata tracked");
 
         // Let the process know we're stopped.
-        SetState (StateType::eStateStopped);
+        CallAfterRunningThreadsStop (pid,
+                                     [=] (lldb::tid_t signaling_tid)
+                                     {
+                                         SetState (StateType::eStateStopped, true);
+                                     });
 
         break;
     }
@@ -2272,7 +2272,11 @@ NativeProcessLinux::MonitorSIGTRAP(const
         // 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);
+        CallAfterRunningThreadsStop (pid,
+                                     [=] (lldb::tid_t signaling_tid)
+                                     {
+                                         SetState (StateType::eStateStopped, true);
+                                     });
         break;
 
     case SI_KERNEL:
@@ -2389,6 +2393,8 @@ NativeProcessLinux::MonitorSignal(const
     //
     // Similarly, ACK signals generated by this monitor.
 
+    Mutex::Locker locker (m_threads_mutex);
+
     // See if we can find a thread for this signal.
     NativeThreadProtocolSP thread_sp = GetThreadByID (pid);
     if (!thread_sp)
@@ -2565,8 +2571,6 @@ NativeProcessLinux::MonitorSignal(const
 Error
 NativeProcessLinux::Resume (const ResumeActionList &resume_actions)
 {
-    Error error;
-
     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
     if (log)
         log->Printf ("NativeProcessLinux::%s called: pid %" PRIu64, __FUNCTION__, GetID ());
@@ -2575,85 +2579,83 @@ NativeProcessLinux::Resume (const Resume
     lldb::tid_t deferred_signal_skip_tid = LLDB_INVALID_THREAD_ID;
     int deferred_signo = 0;
     NativeThreadProtocolSP deferred_signal_thread_sp;
-    int resume_count = 0;
     bool stepping = false;
 
+    Mutex::Locker locker (m_threads_mutex);
 
-    // std::vector<NativeThreadProtocolSP> new_stop_threads;
-
-    // Scope for threads mutex.
+    for (auto thread_sp : m_threads)
     {
-        Mutex::Locker locker (m_threads_mutex);
-        for (auto thread_sp : m_threads)
-        {
-            assert (thread_sp && "thread list should not contain NULL threads");
-
-            const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true);
+        assert (thread_sp && "thread list should not contain NULL threads");
 
-            if (action == nullptr)
-            {
-                if (log)
-                    log->Printf ("NativeProcessLinux::%s no action specified for pid %" PRIu64 " tid %" PRIu64,
-                        __FUNCTION__, GetID (), thread_sp->GetID ());
-                continue;
-            }
+        const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true);
 
+        if (action == nullptr)
+        {
             if (log)
-            {
-                log->Printf ("NativeProcessLinux::%s processing resume action state %s for pid %" PRIu64 " tid %" PRIu64, 
-                        __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ());
-            }
+                log->Printf ("NativeProcessLinux::%s no action specified for pid %" PRIu64 " tid %" PRIu64,
+                    __FUNCTION__, GetID (), thread_sp->GetID ());
+            continue;
+        }
 
-            switch (action->state)
-            {
-            case eStateRunning:
-            {
-                // 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, bool supress_signal)
-                                                               {
-                                                                   reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
-                                                                   // Pass this signal number on to the inferior to handle.
-                                                                   return Resume (tid_to_resume, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
-                                                               },
-                                                               CoordinatorErrorHandler);
-                ++resume_count;
-                break;
-            }
+        if (log)
+        {
+            log->Printf ("NativeProcessLinux::%s processing resume action state %s for pid %" PRIu64 " tid %" PRIu64, 
+                    __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ());
+        }
+
+        switch (action->state)
+        {
+        case eStateRunning:
+        {
+            // 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, bool supress_signal)
+                                                           {
+                                                               reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
+                                                               // Pass this signal number on to the inferior to handle.
+                                                               const auto resume_result = Resume (tid_to_resume, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
+                                                               if (resume_result.Success())
+                                                                   SetState(eStateRunning, true);
+                                                               return resume_result;
+                                                           },
+                                                           CoordinatorErrorHandler);
+            break;
+        }
+
+        case eStateStepping:
+        {
+            // Request the step.
+            const int signo = action->signal;
+            m_coordinator_up->RequestThreadResume (thread_sp->GetID (),
+                                                   [=](lldb::tid_t tid_to_step, bool supress_signal)
+                                                   {
+                                                       reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStepping ();
+                                                       const auto step_result = SingleStep (tid_to_step,(signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
+                                                       assert (step_result.Success() && "SingleStep() failed");
+                                                       if (step_result.Success())
+                                                           SetState(eStateStepping, true);
+                                                       return step_result;
+                                                   },
+                                                   CoordinatorErrorHandler);
+            stepping = true;
+            break;
+        }
 
-            case eStateStepping:
+        case eStateSuspended:
+        case eStateStopped:
+            // if we haven't chosen a deferred signal tid yet, use this one.
+            if (deferred_signal_tid == LLDB_INVALID_THREAD_ID)
             {
-                // Request the step.
-                const int signo = action->signal;
-                m_coordinator_up->RequestThreadResume (thread_sp->GetID (),
-                                                       [=](lldb::tid_t tid_to_step, bool supress_signal)
-                                                       {
-                                                           reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStepping ();
-                                                           const auto step_result = SingleStep (tid_to_step,(signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
-                                                           assert (step_result.Success() && "SingleStep() failed");
-                                                           return step_result;
-                                                       },
-                                                       CoordinatorErrorHandler);
-                stepping = true;
-                break;
+                deferred_signal_tid = thread_sp->GetID ();
+                deferred_signal_thread_sp = thread_sp;
+                deferred_signo = SIGSTOP;
             }
+            break;
 
-            case eStateSuspended:
-            case eStateStopped:
-                // if we haven't chosen a deferred signal tid yet, use this one.
-                if (deferred_signal_tid == LLDB_INVALID_THREAD_ID)
-                {
-                    deferred_signal_tid = thread_sp->GetID ();
-                    deferred_signal_thread_sp = thread_sp;
-                    deferred_signo = SIGSTOP;
-                }
-                break;
-
-            default:
-                return Error ("NativeProcessLinux::%s (): unexpected state %s specified for pid %" PRIu64 ", tid %" PRIu64,
-                        __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ());
-            }
+        default:
+            return Error ("NativeProcessLinux::%s (): unexpected state %s specified for pid %" PRIu64 ", tid %" PRIu64,
+                    __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ());
         }
     }
 
@@ -2677,7 +2679,7 @@ NativeProcessLinux::Resume (const Resume
                                      });
     }
 
-    return error;
+    return Error();
 }
 
 Error
@@ -2728,47 +2730,44 @@ NativeProcessLinux::Interrupt ()
 {
     // Pick a running thread (or if none, a not-dead stopped thread) as
     // the chosen thread that will be the stop-reason thread.
-    Error error;
     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
 
     NativeThreadProtocolSP running_thread_sp;
     NativeThreadProtocolSP stopped_thread_sp;
-    {
-        Mutex::Locker locker (m_threads_mutex);
+        
+    if (log)
+        log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__);
 
-        if (log)
-            log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__);
+    Mutex::Locker locker (m_threads_mutex);
 
-        for (auto thread_sp : m_threads)
+    for (auto thread_sp : m_threads)
+    {
+        // The thread shouldn't be null but lets just cover that here.
+        if (!thread_sp)
+            continue;
+
+        // If we have a running or stepping thread, we'll call that the
+        // target of the interrupt.
+        const auto thread_state = thread_sp->GetState ();
+        if (thread_state == eStateRunning ||
+            thread_state == eStateStepping)
         {
-            // The thread shouldn't be null but lets just cover that here.
-            if (!thread_sp)
-                continue;
-
-            // If we have a running or stepping thread, we'll call that the
-            // target of the interrupt.
-            const auto thread_state = thread_sp->GetState ();
-            if (thread_state == eStateRunning ||
-                thread_state == eStateStepping)
-            {
-                running_thread_sp = thread_sp;
-                break;
-            }
-            else if (!stopped_thread_sp && StateIsStoppedState (thread_state, true))
-            {
-                // Remember the first non-dead stopped thread.  We'll use that as a backup if there are no running threads.
-                stopped_thread_sp = thread_sp;
-            }
+            running_thread_sp = thread_sp;
+            break;
+        }
+        else if (!stopped_thread_sp && StateIsStoppedState (thread_state, true))
+        {
+            // Remember the first non-dead stopped thread.  We'll use that as a backup if there are no running threads.
+            stopped_thread_sp = thread_sp;
         }
     }
 
     if (!running_thread_sp && !stopped_thread_sp)
     {
-        error.SetErrorString ("found no running/stepping or live stopped threads as target for interrupt");
+        Error error("found no running/stepping or live stopped threads as target for interrupt");
         if (log)
-        {
             log->Printf ("NativeProcessLinux::%s skipping due to error: %s", __FUNCTION__, error.AsCString ());
-        }
+
         return error;
     }
 
@@ -2790,10 +2789,10 @@ NativeProcessLinux::Interrupt ()
                                      // Set the thread state as stopped by the deferred signo.
                                      reinterpret_cast<NativeThreadLinux*> (deferred_signal_thread_sp.get ())->SetStoppedBySignal (SIGSTOP);
 
-                                                // Tell the process delegate that the process is in a stopped state.
-                                                SetState (StateType::eStateStopped, true);
-                                            });
-    return error;
+                                     // Tell the process delegate that the process is in a stopped state.
+                                     SetState (StateType::eStateStopped, true);
+                                 });
+    return Error();
 }
 
 Error





More information about the lldb-commits mailing list