[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