diff options
author | Matt Kopec <Matt.Kopec@intel.com> | 2013-07-09 15:09:45 +0000 |
---|---|---|
committer | Matt Kopec <Matt.Kopec@intel.com> | 2013-07-09 15:09:45 +0000 |
commit | b29104467fa6cbc758e0b6b392bbee878fb8d01c (patch) | |
tree | c044905d82e7835a0ed67478864bedb2b2363202 /lldb/source/Plugins/Process | |
parent | ce499744b3339f1690b9a95d6f48a7e09c99916a (diff) | |
download | bcm5719-llvm-b29104467fa6cbc758e0b6b392bbee878fb8d01c.tar.gz bcm5719-llvm-b29104467fa6cbc758e0b6b392bbee878fb8d01c.zip |
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
Diffstat (limited to 'lldb/source/Plugins/Process')
-rw-r--r-- | lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp | 28 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp | 69 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h | 14 |
3 files changed, 89 insertions, 22 deletions
diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp index 512639cecb3..fe617987baa 100644 --- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp +++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp @@ -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(ProcessMonitor *monitor, 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 tid) 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 tid) return true; } // else fall-through - case ProcessMessage::eSignalMessage: case ProcessMessage::eBreakpointMessage: case ProcessMessage::eTraceMessage: case ProcessMessage::eWatchpointMessage: diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp index 6f25585ad3f..e09bfcaf418 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -76,7 +76,8 @@ ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener) 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 ProcessMessage &message) 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 ProcessMessage &message) 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 stop_tid) // 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; +} diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h index 8402aad3496..a865fe26746 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h @@ -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_ |