[Lldb-commits] [lldb] r185944 - Fix signal handling for POSIX (only tested on Linux) processes in multi-threaded programs.

Matt Kopec Matt.Kopec at intel.com
Tue Jul 9 08:09:45 PDT 2013


Author: mkopec
Date: Tue Jul  9 10:09:45 2013
New Revision: 185944

URL: http://llvm.org/viewvc/llvm-project?rev=185944&view=rev
Log:
Fix signal handling for POSIX (only tested on Linux) processes in multi-threaded programs.
Also fix a related issue where if a thread exits after a thread continue, lldb would hang.

Modified:
    lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
    lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
    lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp?rev=185944&r1=185943&r2=185944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp Tue Jul  9 10:09:45 2013
@@ -1236,6 +1236,8 @@ ProcessMonitor::Launch(LaunchArgs *args)
         log->Printf ("ProcessMonitor::%s() adding pid = %" PRIu64, __FUNCTION__, pid);
     process.GetThreadList().AddThread(inferior);
 
+    process.AddThreadForInitialStopIfNeeded(pid);
+
     // Let our process instance know the thread has stopped.
     process.SendMessage(ProcessMessage::Trace(pid));
 
@@ -1294,7 +1296,6 @@ ProcessMonitor::Attach(AttachArgs *args)
 
     // Use a map to keep track of the threads which we have attached/need to attach.
     Host::TidMap tids_to_attach;
-
     if (pid <= 1)
     {
         args->m_error.SetErrorToGenericError();
@@ -1360,6 +1361,7 @@ ProcessMonitor::Attach(AttachArgs *args)
                     log->Printf ("ProcessMonitor::%s() adding tid = %" PRIu64, __FUNCTION__, tid);
                 process.GetThreadList().AddThread(inferior);
                 it->second = true;
+                process.AddThreadForInitialStopIfNeeded(tid);
             }
         }
     }
@@ -1513,7 +1515,7 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMo
         if (!monitor->GetEventMessage(pid, &data))
             data = -1;
         if (log)
-            log->Printf ("ProcessMonitor::%s() received exit event, data = %lx, pid = %" PRIu64, __FUNCTION__, data, pid);
+            log->Printf ("ProcessMonitor::%s() received limbo event, data = %lx, pid = %" PRIu64, __FUNCTION__, data, pid);
         message = ProcessMessage::Limbo(pid, (data >> 8));
         break;
     }
@@ -1711,6 +1713,27 @@ ProcessMonitor::StopThread(lldb::tid_t t
                     return true;
                 break;
 
+            case ProcessMessage::eSignalMessage:
+                if (log)
+                    log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__);
+                if (WSTOPSIG(status) == SIGSTOP)
+                {
+                    m_process->AddThreadForInitialStopIfNeeded(tid);
+                    thread->SetState(lldb::eStateStopped);
+                }
+                else
+                {
+                    m_process->SendMessage(message);
+                    // This isn't the stop we were expecting, but the thread is
+                    // stopped. SendMessage will handle processing of this event,
+                    // but we need to resume here to get the stop we are waiting
+                    // for (otherwise the thread will stop again immediately when
+                    // we try to resume).
+                    if (wait_pid == tid)
+                        Resume(wait_pid, eResumeSignalNone);
+                }
+                break;
+
             case ProcessMessage::eSignalDeliveredMessage:
                 // This is the stop we're expecting.
                 if (wait_pid == tid && WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP && info.si_code == SI_TKILL)
@@ -1721,7 +1744,6 @@ ProcessMonitor::StopThread(lldb::tid_t t
                     return true;
                 }
                 // else fall-through
-            case ProcessMessage::eSignalMessage:
             case ProcessMessage::eBreakpointMessage:
             case ProcessMessage::eTraceMessage:
             case ProcessMessage::eWatchpointMessage:

Modified: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp?rev=185944&r1=185943&r2=185944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp Tue Jul  9 10:09:45 2013
@@ -76,7 +76,8 @@ ProcessPOSIX::ProcessPOSIX(Target& targe
       m_monitor(NULL),
       m_module(NULL),
       m_message_mutex (Mutex::eMutexTypeRecursive),
-      m_exit_now(false)
+      m_exit_now(false),
+      m_seen_initial_stop()
 {
     // FIXME: Putting this code in the ctor and saving the byte order in a
     // member variable is a hack to avoid const qual issues in GetByteOrder.
@@ -412,13 +413,10 @@ ProcessPOSIX::SendMessage(const ProcessM
             m_exit_status = message.GetExitStatus();
             SetExitStatus(m_exit_status, NULL);
         }
+        else if (!IsAThreadRunning())
+            SetPrivateState(eStateStopped);
         break;
 
-    case ProcessMessage::eBreakpointMessage:
-    case ProcessMessage::eTraceMessage:
-    case ProcessMessage::eWatchpointMessage:
-    case ProcessMessage::eNewThreadMessage:
-    case ProcessMessage::eCrashMessage:
         assert(thread);
         thread->SetState(eStateStopped);
         StopAllThreads(message.GetTID());
@@ -427,21 +425,21 @@ ProcessPOSIX::SendMessage(const ProcessM
 
     case ProcessMessage::eSignalMessage:
     case ProcessMessage::eSignalDeliveredMessage:
-    {
-        lldb::tid_t tid = message.GetTID();
-        lldb::tid_t pid = GetID();
-        if (tid == pid) {
-            assert(thread);
-            thread->SetState(eStateStopped);
-            StopAllThreads(message.GetTID());
-            SetPrivateState(eStateStopped);
-            break;
-        } else {
-            // FIXME: Ignore any signals generated by children.
+        if (message.GetSignal() == SIGSTOP &&
+            AddThreadForInitialStopIfNeeded(message.GetTID()))
             return;
-        }
-    }
+        // Intentional fall-through
 
+    case ProcessMessage::eBreakpointMessage:
+    case ProcessMessage::eTraceMessage:
+    case ProcessMessage::eWatchpointMessage:
+    case ProcessMessage::eNewThreadMessage:
+    case ProcessMessage::eCrashMessage:
+        assert(thread);
+        thread->SetState(eStateStopped);
+        StopAllThreads(message.GetTID());
+        SetPrivateState(eStateStopped);
+        break;
     }
 
     m_message_queue.push(message);
@@ -453,6 +451,19 @@ ProcessPOSIX::StopAllThreads(lldb::tid_t
     // FIXME: Will this work the same way on FreeBSD and Linux?
 }
 
+bool
+ProcessPOSIX::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
+{
+    bool added_to_set = false;
+    ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
+    if (it == m_seen_initial_stop.end())
+    {
+        m_seen_initial_stop.insert(stop_tid);
+        added_to_set = true;
+    }
+    return added_to_set;
+}
+
 void
 ProcessPOSIX::RefreshStateAfterStop()
 {
@@ -497,6 +508,7 @@ ProcessPOSIX::RefreshStateAfterStop()
                 log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
             ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
             thread_sp.reset();
+            m_seen_initial_stop.erase(tid);
         }
 
         m_message_queue.pop();
@@ -851,3 +863,22 @@ ProcessPOSIX::IsStopped()
 
     return false;
 }
+
+bool
+ProcessPOSIX::IsAThreadRunning()
+{
+    bool is_running = false;
+    uint32_t thread_count = m_thread_list.GetSize(false);
+    for (uint32_t i = 0; i < thread_count; ++i)
+    {
+        POSIXThread *thread = static_cast<POSIXThread*>(
+            m_thread_list.GetThreadAtIndex(i, false).get());
+        StateType thread_state = thread->GetState();
+        if (thread_state == eStateRunning || thread_state == eStateStepping)
+        {
+            is_running = true;
+            break;
+        }
+    }
+    return is_running;
+}

Modified: lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h?rev=185944&r1=185943&r2=185944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h Tue Jul  9 10:09:45 2013
@@ -14,6 +14,7 @@
 
 // C++ Includes
 #include <queue>
+#include <set>
 
 // Other libraries and framework includes
 #include "lldb/Target/Process.h"
@@ -157,6 +158,11 @@ public:
     virtual void
     StopAllThreads(lldb::tid_t stop_tid);
 
+    /// Adds the thread to the list of threads for which we have received the initial stopping signal.
+    /// The \p stop_tid paramter indicates the thread which the stop happened for.
+    bool
+    AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
+
 protected:
     /// Target byte order.
     lldb::ByteOrder m_byte_order;
@@ -183,8 +189,16 @@ protected:
     /// Returns true if the process is stopped.
     bool IsStopped();
 
+    /// Returns true if at least one running is currently running
+    bool IsAThreadRunning();
+
     typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
     MMapMap m_addr_to_mmap_size;
+
+    typedef std::set<lldb::tid_t> ThreadStopSet;
+    /// Every thread begins with a stop signal. This keeps track
+    /// of the threads for which we have received the stop signal.
+    ThreadStopSet m_seen_initial_stop;
 };
 
 #endif  // liblldb_MacOSXProcess_H_





More information about the lldb-commits mailing list