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.

llvm-svn: 185944
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index 6f25585..e09bfca 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -76,7 +76,8 @@
       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,8 +413,23 @@
             m_exit_status = message.GetExitStatus();
             SetExitStatus(m_exit_status, NULL);
         }
+        else if (!IsAThreadRunning())
+            SetPrivateState(eStateStopped);
         break;
 
+        assert(thread);
+        thread->SetState(eStateStopped);
+        StopAllThreads(message.GetTID());
+        SetPrivateState(eStateStopped);
+        break;
+
+    case ProcessMessage::eSignalMessage:
+    case ProcessMessage::eSignalDeliveredMessage:
+        if (message.GetSignal() == SIGSTOP &&
+            AddThreadForInitialStopIfNeeded(message.GetTID()))
+            return;
+        // Intentional fall-through
+
     case ProcessMessage::eBreakpointMessage:
     case ProcessMessage::eTraceMessage:
     case ProcessMessage::eWatchpointMessage:
@@ -424,24 +440,6 @@
         StopAllThreads(message.GetTID());
         SetPrivateState(eStateStopped);
         break;
-
-    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.
-            return;
-        }
-    }
-
     }
 
     m_message_queue.push(message);
@@ -453,6 +451,19 @@
     // 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 @@
                 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 @@
 
     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;
+}