[Lldb-commits] [lldb] r190831 - Fixing a problem with thread creation signal order dependency

Andrew Kaylor andrew.kaylor at intel.com
Mon Sep 16 17:30:25 PDT 2013


Author: akaylor
Date: Mon Sep 16 19:30:24 2013
New Revision: 190831

URL: http://llvm.org/viewvc/llvm-project?rev=190831&view=rev
Log:
Fixing a problem with thread creation signal order dependency

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

Modified: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp?rev=190831&r1=190830&r2=190831&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (original)
+++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp Mon Sep 16 19:30:24 2013
@@ -1637,6 +1637,29 @@ ProcessMonitor::StopMonitor()
     // even though still has the file descriptor, we shouldn't close it here.
 }
 
+// FIXME: On Linux, when a new thread is created, we receive to notifications,
+// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the
+// child thread id as additional information, and (2) a SIGSTOP|SI_USER from
+// the new child thread indicating that it has is stopped because we attached.
+// We have no guarantee of the order in which these arrive, but we need both
+// before we are ready to proceed.  We currently keep a list of threads which
+// have sent the initial SIGSTOP|SI_USER event.  Then when we receive the
+// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred
+// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
+//
+// Right now, the above logic is in ProcessPOSIX, so we need a definition of
+// this function in the FreeBSD ProcessMonitor implementation even if it isn't
+// logically needed.
+//
+// We really should figure out what actually happens on FreeBSD and move the
+// Linux-specific logic out of ProcessPOSIX as needed.
+
+bool
+ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid)
+{
+    return true;
+}
+
 void
 ProcessMonitor::StopOpThread()
 {

Modified: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h?rev=190831&r1=190830&r2=190831&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h (original)
+++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h Mon Sep 16 19:30:24 2013
@@ -193,6 +193,10 @@ public:
     void
     StopMonitor();
 
+    // Waits for the initial stop message from a new thread.
+    bool
+    WaitForInitialTIDStop(lldb::tid_t tid);
+
 private:
     ProcessFreeBSD *m_process;
 

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=190831&r1=190830&r2=190831&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp Mon Sep 16 19:30:24 2013
@@ -1595,6 +1595,80 @@ ProcessMonitor::MonitorSignal(ProcessMon
     return ProcessMessage::Signal(pid, signo);
 }
 
+// On Linux, when a new thread is created, we receive to notifications,
+// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the
+// child thread id as additional information, and (2) a SIGSTOP|SI_USER from
+// the new child thread indicating that it has is stopped because we attached.
+// We have no guarantee of the order in which these arrive, but we need both
+// before we are ready to proceed.  We currently keep a list of threads which
+// have sent the initial SIGSTOP|SI_USER event.  Then when we receive the
+// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred
+// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
+
+bool
+ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid)
+{
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessMonitor::%s(%d) waiting for thread to stop...", __FUNCTION__, tid);
+
+    // Wait for the thread to stop
+    while (true)
+    {
+        int status = -1;
+        if (log)
+            log->Printf ("ProcessMonitor::%s(%d) waitpid...", __FUNCTION__, tid);
+        lldb::pid_t wait_pid = waitpid(tid, &status, __WALL);
+        if (status == -1)
+        {
+            // If we got interrupted by a signal (in our process, not the
+            // inferior) try again.
+            if (errno == EINTR)
+                continue;
+            else
+            {
+                if (log)
+                    log->Printf("ProcessMonitor::%s(%d) waitpid error -- %s", __FUNCTION__, tid, strerror(errno));
+                return false; // This is bad, but there's nothing we can do.
+            }
+        }
+
+        if (log)
+            log->Printf ("ProcessMonitor::%s(%d) waitpid, status = %d", __FUNCTION__, tid, status);
+
+        assert(wait_pid == tid);
+
+        siginfo_t info;
+        int ptrace_err;
+        if (!GetSignalInfo(wait_pid, &info, ptrace_err))
+        {
+            if (log)
+            {
+                log->Printf ("ProcessMonitor::%s() GetSignalInfo failed. errno=%d (%s)", __FUNCTION__, ptrace_err, strerror(ptrace_err));
+            }
+            return false;
+        }
+
+        // If this is a thread exit, we won't get any more information.
+        if (WIFEXITED(status))
+        {
+            m_process->SendMessage(ProcessMessage::Exit(wait_pid, WEXITSTATUS(status)));
+            if (wait_pid == tid)
+                return true;
+            continue;
+        }
+
+        assert(info.si_code == SI_USER);
+        assert(WSTOPSIG(status) == SIGSTOP);
+
+        if (log)
+            log->Printf ("ProcessMonitor::%s(bp) received thread stop signal", __FUNCTION__);
+        m_process->AddThreadForInitialStopIfNeeded(wait_pid);
+        return true;
+    }
+    return false;
+}
+
 bool
 ProcessMonitor::StopThread(lldb::tid_t tid)
 {

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h?rev=190831&r1=190830&r2=190831&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h Mon Sep 16 19:30:24 2013
@@ -185,6 +185,10 @@ public:
     bool
     StopThread(lldb::tid_t tid);
 
+    // Waits for the initial stop message from a new thread.
+    bool
+    WaitForInitialTIDStop(lldb::tid_t tid);
+
 private:
     ProcessLinux *m_process;
 

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=190831&r1=190830&r2=190831&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp Mon Sep 16 19:30:24 2013
@@ -418,13 +418,26 @@ ProcessPOSIX::SendMessage(const ProcessM
     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;
+
+    case ProcessMessage::eNewThreadMessage:
+        {
+        lldb::tid_t  new_tid = message.GetChildTID();
+        if (WaitingForInitialStop(new_tid))
+        {
+            m_monitor->WaitForInitialTIDStop(new_tid);
+        }
+        assert(thread);
+        thread->SetState(eStateStopped);
+        StopAllThreads(message.GetTID());
+        SetPrivateState(eStateStopped);
+        break;
+        }
     }
 
     m_message_queue.push(message);
@@ -449,6 +462,12 @@ ProcessPOSIX::AddThreadForInitialStopIfN
     return added_to_set;
 }
 
+bool
+ProcessPOSIX::WaitingForInitialStop(lldb::tid_t stop_tid)
+{
+    return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
+}
+
 POSIXThread *
 ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid)
 {

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=190831&r1=190830&r2=190831&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h Mon Sep 16 19:30:24 2013
@@ -167,6 +167,9 @@ public:
     bool
     AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
 
+    bool
+    WaitingForInitialStop(lldb::tid_t stop_tid);
+
     virtual POSIXThread *
     CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid);
 





More information about the lldb-commits mailing list