summaryrefslogtreecommitdiffstats
path: root/lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp
diff options
context:
space:
mode:
authorTodd Fiala <todd.fiala@gmail.com>2014-09-30 16:56:28 +0000
committerTodd Fiala <todd.fiala@gmail.com>2014-09-30 16:56:28 +0000
commitf8d929dc827000d109a5c619648fa239b79a18e9 (patch)
tree8e4b8a4dfc86d7dd47a9c303a3c7d43f8dfbaf1a /lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp
parent7a770755305f19426e5748195035a26e6e673077 (diff)
downloadbcm5719-llvm-f8d929dc827000d109a5c619648fa239b79a18e9.tar.gz
bcm5719-llvm-f8d929dc827000d109a5c619648fa239b79a18e9.zip
thread state coordinator: add test to be explicit about resume behavior in presence of deferred stop notification still pending.
There is a state transition that seems potentially buggy that I am capturing and logging here, and including an explicit test to demonstrate expected behavior. See new test for detailed description. Added logging around this area since, if we hit it, we may have a usage bug, or a new state transition we really need to investigate. This is around this scenario: Thread C deferred stop notification awaiting thread A and thread B to stop. Thread A stops. Thread A requests resume. Thread B stops. Here we will explicitly signal the deferred stop notification after thread B stops even though thread A is now resumed. Copious logging happens here. llvm-svn: 218683
Diffstat (limited to 'lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp')
-rw-r--r--lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp b/lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp
index f9ca339e4fa..59e7b806329 100644
--- a/lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp
+++ b/lldb/gtest/unittest/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp
@@ -499,3 +499,81 @@ TEST(ThreadStateCoordinatorTest, RequestThreadResumeIgnoresCallbackWhenThreadIsR
// The resume request should not have gone off because we think it is already running.
ASSERT_EQ (0, resume_call_count);
}
+
+TEST(ThreadStateCoordinatorTest, ResumedThreadAlreadyMarkedDoesNotHoldUpPendingStopNotification)
+{
+ // We're going to test this scenario:
+ // * Deferred notification waiting on two threads, A and B. A and B currently running.
+ // * Thread A stops.
+ // * Thread A resumes.
+ // * Thread B stops.
+ //
+ // Here we could have forced A to stop again (after the Thread A resumes) because we had a pending stop nofication awaiting
+ // all those threads to stop. However, we are going to explicitly not try to restop A - somehow
+ // that seems wrong and possibly buggy since for that to happen, we would have intentionally called
+ // a resume after the stop. Instead, we'll just log and indicate this looks suspicous. We can revisit
+ // that decision after we see if/when that happens.
+
+ ThreadStateCoordinator coordinator(StdoutLogger);
+
+ const lldb::tid_t TRIGGERING_TID = 4105;
+ const lldb::tid_t PENDING_TID_A = 2;
+ const lldb::tid_t PENDING_TID_B = 89;
+
+ ThreadStateCoordinator::ThreadIDSet pending_stop_tids { PENDING_TID_A, PENDING_TID_B };
+
+ bool call_after_fired = false;
+ lldb::tid_t reported_firing_tid = 0;
+
+ int request_thread_stop_calls = 0;
+ ThreadStateCoordinator::ThreadIDSet request_thread_stop_tids;
+
+ // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped.
+ coordinator.CallAfterThreadsStop (TRIGGERING_TID,
+ pending_stop_tids,
+ [&](lldb::tid_t tid) {
+ ++request_thread_stop_calls;
+ request_thread_stop_tids.insert (tid);
+
+ },
+ [&](lldb::tid_t tid) {
+ call_after_fired = true;
+ reported_firing_tid = tid;
+ });
+
+ // Neither trigger should have gone off yet.
+ ASSERT_EQ (false, call_after_fired);
+ ASSERT_EQ (0, request_thread_stop_calls);
+
+ // Execute CallAfterThreadsStop.
+ ASSERT_EQ (true, coordinator.ProcessNextEvent ());
+
+ // Both TID A and TID B should have had stop requests made.
+ ASSERT_EQ (2, request_thread_stop_calls);
+ ASSERT_EQ (1, request_thread_stop_tids.count (PENDING_TID_A));
+
+ // But we still shouldn't have the deferred signal call go off yet.
+ ASSERT_EQ (false, call_after_fired);
+
+ // Report thread A stopped.
+ coordinator.NotifyThreadStop (PENDING_TID_A);
+ ASSERT_EQ (true, coordinator.ProcessNextEvent ());
+ ASSERT_EQ (false, call_after_fired);
+
+ // Now report thread A is resuming. Ensure the resume is called.
+ bool resume_called = false;
+ coordinator.RequestThreadResume (PENDING_TID_A, [&](lldb::tid_t tid) { resume_called = true; } );
+ ASSERT_EQ (false, resume_called);
+ ASSERT_EQ (true, coordinator.ProcessNextEvent ());
+ ASSERT_EQ (true, resume_called);
+
+ // Report thread B stopped.
+ coordinator.NotifyThreadStop (PENDING_TID_B);
+ ASSERT_EQ (false, call_after_fired);
+ ASSERT_EQ (true, coordinator.ProcessNextEvent ());
+
+ // After notifying thread b stopped, we now have thread a resumed but thread b stopped.
+ // However, since thread a had stopped, we now have had both requirements stopped at some point.
+ // For now we'll expect this will fire the pending deferred stop notification.
+ ASSERT_EQ (true, call_after_fired);
+}
OpenPOWER on IntegriCloud