thread state coordinator: add tests and impl to error on creation/death issues.

Added tests and impl to make sure the following errors are reported:
* Notifying a created thread that we are already tracking.
* Notifying a thread death for a thread we don't know about.

llvm-svn: 218900
This commit is contained in:
Todd Fiala 2014-10-02 19:44:32 +00:00
parent ee7902d3b2
commit b72209102f
3 changed files with 49 additions and 7 deletions

View File

@ -205,6 +205,26 @@ TEST_F (ThreadStateCoordinatorTest, StopCoordinatorWorksNoPriorEvents)
ASSERT_EQ (false, HasError ());
}
TEST_F (ThreadStateCoordinatorTest, NotifyThreadCreateSignalsErrorOnAlreadyKnownThread)
{
// Let the coordinator know about our thread.
SetupKnownStoppedThread (TRIGGERING_TID);
// Notify an unknown thread has stopped.
NotifyThreadCreate (TRIGGERING_TID, true);
ASSERT_PROCESS_NEXT_EVENT_FAILS ();
}
TEST_F (ThreadStateCoordinatorTest, NotifyThreadDeathSignalsErrorOnUnknownThread)
{
const lldb::tid_t UNKNOWN_TID = 678;
// Notify an unknown thread has stopped.
NotifyThreadDeath (UNKNOWN_TID);
ASSERT_PROCESS_NEXT_EVENT_FAILS ();
}
TEST_F (ThreadStateCoordinatorTest, NotifyThreadStopSignalsErrorOnUnknownThread)
{
const lldb::tid_t UNKNOWN_TID = 678;

View File

@ -337,7 +337,7 @@ public:
EventLoopResult
ProcessEvent(ThreadStateCoordinator &coordinator) override
{
coordinator.ThreadWasCreated (m_tid, m_is_stopped);
coordinator.ThreadWasCreated (m_tid, m_is_stopped, m_error_function);
return eventLoopResultContinue;
}
@ -364,7 +364,7 @@ public:
EventLoopResult
ProcessEvent(ThreadStateCoordinator &coordinator) override
{
coordinator.ThreadDidDie (m_tid);
coordinator.ThreadDidDie (m_tid, m_error_function);
return eventLoopResultContinue;
}
@ -568,8 +568,19 @@ ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, ErrorFunction &error_fun
}
void
ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid, bool is_stopped)
ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function)
{
// Ensure we don't already know about the thread.
auto find_it = m_tid_stop_map.find (tid);
if (find_it != m_tid_stop_map.end ())
{
// We already know about this thread. This is an error condition.
std::ostringstream error_message;
error_message << "error: notified tid " << tid << " created but we already know about this thread";
error_function (error_message.str ());
return;
}
// Add the new thread to the stop map.
m_tid_stop_map[tid] = is_stopped;
@ -583,12 +594,23 @@ ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid, bool is_stopped)
}
void
ThreadStateCoordinator::ThreadDidDie (lldb::tid_t tid)
ThreadStateCoordinator::ThreadDidDie (lldb::tid_t tid, ErrorFunction &error_function)
{
// Ensure we know about the thread.
auto find_it = m_tid_stop_map.find (tid);
if (find_it == m_tid_stop_map.end ())
{
// We don't know about this thread. This is an error condition.
std::ostringstream error_message;
error_message << "error: notified tid " << tid << " died but tid is unknown";
error_function (error_message.str ());
return;
}
// Update the global list of known thread states. While this one is stopped, it is also dead.
// So stop tracking it. We assume the user of this coordinator will not keep trying to add
// dependencies on a thread after it is known to be dead.
m_tid_stop_map.erase (tid);
m_tid_stop_map.erase (find_it);
// If we have a pending notification, remove this from the set.
EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();

View File

@ -150,10 +150,10 @@ namespace lldb_private
ThreadDidStop (lldb::tid_t tid, ErrorFunction &error_function);
void
ThreadWasCreated (lldb::tid_t tid, bool is_stopped);
ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function);
void
ThreadDidDie (lldb::tid_t tid);
ThreadDidDie (lldb::tid_t tid, ErrorFunction &error_function);
void
ResetNow ();