Adding support for stopping all threads of multithreaded inferiors on Linux. Also adding multithreaded test cases.
llvm-svn: 182809
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index 471843b..b2db43e 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -75,6 +75,7 @@
m_byte_order(lldb::endian::InlHostByteOrder()),
m_monitor(NULL),
m_module(NULL),
+ m_message_mutex (Mutex::eMutexTypeRecursive),
m_in_limbo(false),
m_exit_now(false)
{
@@ -374,31 +375,58 @@
{
Mutex::Locker lock(m_message_mutex);
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ m_thread_list.FindThreadByID(message.GetTID(), false).get());
+
switch (message.GetKind())
{
case ProcessMessage::eInvalidMessage:
return;
case ProcessMessage::eLimboMessage:
- m_in_limbo = true;
- m_exit_status = message.GetExitStatus();
- if (m_exit_now)
+ assert(thread);
+ thread->SetState(eStateStopped);
+ if (message.GetTID() == GetID())
{
- SetPrivateState(eStateExited);
- m_monitor->Detach();
+ m_in_limbo = true;
+ m_exit_status = message.GetExitStatus();
+ if (m_exit_now)
+ {
+ SetPrivateState(eStateExited);
+ m_monitor->Detach();
+ }
+ else
+ {
+ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
+ }
}
else
+ {
+ StopAllThreads(message.GetTID());
SetPrivateState(eStateStopped);
+ }
break;
case ProcessMessage::eExitMessage:
- m_exit_status = message.GetExitStatus();
- SetExitStatus(m_exit_status, NULL);
+ assert(thread);
+ thread->SetState(eStateExited);
+ // FIXME: I'm not sure we need to do this.
+ if (message.GetTID() == GetID())
+ {
+ m_exit_status = message.GetExitStatus();
+ SetExitStatus(m_exit_status, NULL);
+ }
break;
- case ProcessMessage::eTraceMessage:
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;
@@ -408,6 +436,9 @@
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 {
@@ -416,51 +447,65 @@
}
}
- case ProcessMessage::eCrashMessage:
- // FIXME: Update stop reason as per bugzilla 14598
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eNewThreadMessage:
- SetPrivateState(eStateStopped);
- break;
}
m_message_queue.push(message);
}
+void
+ProcessPOSIX::StopAllThreads(lldb::tid_t stop_tid)
+{
+ // FIXME: Will this work the same way on FreeBSD and Linux?
+}
+
void
ProcessPOSIX::RefreshStateAfterStop()
{
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s()", __FUNCTION__);
+ log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
Mutex::Locker lock(m_message_mutex);
- if (m_message_queue.empty())
- return;
- ProcessMessage &message = m_message_queue.front();
+ // This method used to only handle one message. Changing it to loop allows
+ // it to handle the case where we hit a breakpoint while handling a different
+ // breakpoint.
+ while (!m_message_queue.empty())
+ {
+ ProcessMessage &message = m_message_queue.front();
- // Resolve the thread this message corresponds to and pass it along.
- // FIXME: we're really dealing with the pid here. This should get
- // fixed when this code is fixed to handle multiple threads.
- lldb::tid_t tid = message.GetTID();
- if (log)
- log->Printf ("ProcessPOSIX::%s() pid = %" PRIi64, __FUNCTION__, tid);
- POSIXThread *thread = static_cast<POSIXThread*>(
- GetThreadList().FindThreadByID(tid, false).get());
+ // Resolve the thread this message corresponds to and pass it along.
+ lldb::tid_t tid = message.GetTID();
+ if (log)
+ log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
+ POSIXThread *thread = static_cast<POSIXThread*>(
+ GetThreadList().FindThreadByID(tid, false).get());
- if (message.GetKind() == ProcessMessage::eNewThreadMessage) {
- ThreadSP thread_sp;
- thread_sp.reset(new POSIXThread(*this, message.GetChildTID()));
- m_thread_list.AddThread(thread_sp);
+ if (message.GetKind() == ProcessMessage::eNewThreadMessage)
+ {
+ if (log)
+ log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID());
+ ThreadSP thread_sp;
+ thread_sp.reset(new POSIXThread(*this, message.GetChildTID()));
+ m_thread_list.AddThread(thread_sp);
+ }
+
+ m_thread_list.RefreshStateAfterStop();
+
+ if (thread)
+ thread->Notify(message);
+
+ if (message.GetKind() == ProcessMessage::eExitMessage)
+ {
+ // FIXME: We should tell the user about this, but the limbo message is probably better for that.
+ if (log)
+ log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
+ ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
+ thread_sp.reset();
+ }
+
+ m_message_queue.pop();
}
-
- assert(thread);
- thread->Notify(message);
-
- m_message_queue.pop();
}
bool