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;
+}