Index: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -110,6 +110,12 @@ Error SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) override; + Error + SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override; + + Error + RemoveWatchpoint (lldb::addr_t addr) override; + void DoStopIDBumped (uint32_t newBumpId) override; @@ -185,7 +191,6 @@ Mutex m_mem_region_cache_mutex; std::unique_ptr m_coordinator_up; - HostThread m_coordinator_thread; // List of thread ids stepping with a breakpoint with the address of // the relevan breakpoint @@ -303,19 +308,6 @@ GetCrashReasonForSIGBUS(const siginfo_t *info); #endif - Error - StartCoordinatorThread (); - - static void* - CoordinatorThread (void *arg); - - void - StopCoordinatorThread (); - - /// Stops monitoring the child process thread. - void - StopMonitor(); - bool HasThreadNoLock (lldb::tid_t thread_id); Index: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -1069,7 +1069,6 @@ { PTRACE(PTRACE_DETACH, m_tid, nullptr, 0, 0, m_error); } - } // end of anonymous namespace // Simple helper function to ensure flags are enabled on the given file @@ -1105,7 +1104,8 @@ // pipe, and the completion of the operation is signalled over the semaphore. // - thread exit event: this is signaled from the Monitor destructor by closing the write end // of the command pipe. -class NativeProcessLinux::Monitor { +class NativeProcessLinux::Monitor +{ private: // The initial monitor operation (launch or attach). It returns a inferior process id. std::unique_ptr m_initial_operation_up; @@ -1124,7 +1124,11 @@ sem_t m_operation_sem; Error m_operation_error; - static constexpr char operation_command = 'o'; + unsigned m_operation_nesting_level = 0; + + static constexpr char operation_command = 'o'; + static constexpr char begin_block_command = '{'; + static constexpr char end_block_command = '}'; void HandleSignals(); @@ -1143,7 +1147,22 @@ RunMonitor(void *arg); Error - WaitForOperation(); + WaitForAck(); + + void + BeginOperationBlock() + { + write(m_pipefd[WRITE], &begin_block_command, sizeof operation_command); + WaitForAck(); + } + + void + EndOperationBlock() + { + write(m_pipefd[WRITE], &end_block_command, sizeof operation_command); + WaitForAck(); + } + public: Monitor(const InitialOperation &initial_operation, NativeProcessLinux *native_process) @@ -1159,9 +1178,26 @@ Initialize(); void + Terminate(); + + void DoOperation(Operation *op); + + class ScopedOperationLock { + Monitor &m_monitor; + + public: + ScopedOperationLock(Monitor &monitor) + : m_monitor(monitor) + { m_monitor.BeginOperationBlock(); } + + ~ScopedOperationLock() + { m_monitor.EndOperationBlock(); } + }; }; constexpr char NativeProcessLinux::Monitor::operation_command; +constexpr char NativeProcessLinux::Monitor::begin_block_command; +constexpr char NativeProcessLinux::Monitor::end_block_command; Error NativeProcessLinux::Monitor::Initialize() @@ -1198,7 +1234,7 @@ return Error("Failed to create monitor thread for NativeProcessLinux."); // Wait for initial operation to complete. - return WaitForOperation(); + return WaitForAck(); } void @@ -1218,15 +1254,24 @@ // notify the thread that an operation is ready to be processed write(m_pipefd[WRITE], &operation_command, sizeof operation_command); - WaitForOperation(); + WaitForAck(); } -NativeProcessLinux::Monitor::~Monitor() +void +NativeProcessLinux::Monitor::Terminate() { if (m_pipefd[WRITE] >= 0) + { close(m_pipefd[WRITE]); + m_pipefd[WRITE] = -1; + } if (m_thread.IsJoinable()) m_thread.Join(nullptr); +} + +NativeProcessLinux::Monitor::~Monitor() +{ + Terminate(); if (m_pipefd[READ] >= 0) close(m_pipefd[READ]); if (m_signal_fd >= 0) @@ -1356,6 +1401,7 @@ { if (log) log->Printf("NativeProcessLinux::Monitor::%s exit command received, exiting...", __FUNCTION__); + assert(m_operation_nesting_level == 0 && "Unbalanced begin/end block commands detected"); return true; // We are done. } @@ -1363,15 +1409,22 @@ { case operation_command: m_operation->Execute(m_native_process); - - // notify calling thread that operation is complete - sem_post(&m_operation_sem); + break; + case begin_block_command: + ++m_operation_nesting_level; + break; + case end_block_command: + assert(m_operation_nesting_level > 0); + --m_operation_nesting_level; break; default: if (log) log->Printf("NativeProcessLinux::Monitor::%s received unknown command '%c'", __FUNCTION__, command); } + + // notify calling thread that the command has been processed + sem_post(&m_operation_sem); } } @@ -1387,7 +1440,10 @@ { fd_set fds; FD_ZERO(&fds); - FD_SET(m_signal_fd, &fds); + // Only process waitpid events if we are outside of an operation block. Any pending + // events will be processed after we leave the block. + if (m_operation_nesting_level == 0) + FD_SET(m_signal_fd, &fds); FD_SET(m_pipefd[READ], &fds); int max_fd = std::max(m_signal_fd, m_pipefd[READ]) + 1; @@ -1416,7 +1472,7 @@ } Error -NativeProcessLinux::Monitor::WaitForOperation() +NativeProcessLinux::Monitor::WaitForAck() { Error error; while (sem_wait(&m_operation_sem) != 0) @@ -1617,8 +1673,7 @@ m_supports_mem_region (eLazyBoolCalculate), m_mem_region_cache (), m_mem_region_cache_mutex (), - m_coordinator_up (new ThreadStateCoordinator (GetThreadLoggerFunction ())), - m_coordinator_thread () + m_coordinator_up (new ThreadStateCoordinator (GetThreadLoggerFunction ())) { } @@ -1652,10 +1707,6 @@ StartMonitorThread ([&] (Error &e) { return Launch(args.get(), e); }, error); if (!error.Success ()) return; - - error = StartCoordinatorThread (); - if (!error.Success ()) - return; } void @@ -1705,16 +1756,12 @@ StartMonitorThread ([=] (Error &e) { return Attach(pid, e); }, error); if (!error.Success ()) return; - - error = StartCoordinatorThread (); - if (!error.Success ()) - return; } void NativeProcessLinux::Terminate () { - StopMonitor(); + m_monitor_up->Terminate(); } ::pid_t @@ -2997,6 +3044,7 @@ bool stepping = false; bool software_single_step = !SupportHardwareSingleStepping(); + Monitor::ScopedOperationLock monitor_lock(*m_monitor_up); Mutex::Locker locker (m_threads_mutex); if (software_single_step) @@ -3144,7 +3192,7 @@ error = Detach (GetID ()); // Stop monitoring the inferior. - StopMonitor (); + m_monitor_up->Terminate(); // No error. return error; @@ -3179,6 +3227,7 @@ if (log) log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__); + Monitor::ScopedOperationLock monitor_lock(*m_monitor_up); Mutex::Locker locker (m_threads_mutex); for (auto thread_sp : m_threads) @@ -3233,6 +3282,7 @@ // Tell the process delegate that the process is in a stopped state. SetState (StateType::eStateStopped, true); }); + return Error(); } @@ -3834,7 +3884,25 @@ #endif Error -NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) +NativeProcessLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) +{ + // The base SetWatchpoint will end up executing monitor operations. Let's lock the monitor + // for it. + Monitor::ScopedOperationLock monitor_lock(*m_monitor_up); + return NativeProcessProtocol::SetWatchpoint(addr, size, watch_flags, hardware); +} + +Error +NativeProcessLinux::RemoveWatchpoint (lldb::addr_t addr) +{ + // The base RemoveWatchpoint will end up executing monitor operations. Let's lock the monitor + // for it. + Monitor::ScopedOperationLock monitor_lock(*m_monitor_up); + return NativeProcessProtocol::RemoveWatchpoint(addr); +} + +Error +NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) { ReadOperation op(addr, buf, size, bytes_read); m_monitor_up->DoOperation(&op); @@ -3997,77 +4065,6 @@ } } -void -NativeProcessLinux::StopMonitor() -{ - StopCoordinatorThread (); - m_monitor_up.reset(); -} - -Error -NativeProcessLinux::StartCoordinatorThread () -{ - Error error; - static const char *g_thread_name = "lldb.process.linux.ts_coordinator"; - Log *const log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - - // Skip if thread is already running - if (m_coordinator_thread.IsJoinable()) - { - error.SetErrorString ("ThreadStateCoordinator's run loop is already running"); - if (log) - log->Printf ("NativeProcessLinux::%s %s", __FUNCTION__, error.AsCString ()); - return error; - } - - // Enable verbose logging if lldb thread logging is enabled. - m_coordinator_up->LogEnableEventProcessing (log != nullptr); - - if (log) - log->Printf ("NativeProcessLinux::%s launching ThreadStateCoordinator thread for pid %" PRIu64, __FUNCTION__, GetID ()); - m_coordinator_thread = ThreadLauncher::LaunchThread(g_thread_name, CoordinatorThread, this, &error); - return error; -} - -void * -NativeProcessLinux::CoordinatorThread (void *arg) -{ - Log *const log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - - NativeProcessLinux *const process = static_cast (arg); - assert (process && "null process passed to CoordinatorThread"); - if (!process) - { - if (log) - log->Printf ("NativeProcessLinux::%s null process, exiting ThreadStateCoordinator processing loop", __FUNCTION__); - return nullptr; - } - - // Run the thread state coordinator loop until it is done. This call uses - // efficient waiting for an event to be ready. - while (process->m_coordinator_up->ProcessNextEvent () == ThreadStateCoordinator::eventLoopResultContinue) - { - } - - if (log) - log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " exiting ThreadStateCoordinator processing loop due to coordinator indicating completion", __FUNCTION__, process->GetID ()); - - return nullptr; -} - -void -NativeProcessLinux::StopCoordinatorThread() -{ - Log *const log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - if (log) - log->Printf ("NativeProcessLinux::%s requesting ThreadStateCoordinator stop for pid %" PRIu64, __FUNCTION__, GetID ()); - - // Tell the coordinator we're done. This will cause the coordinator - // run loop thread to exit when the processing queue hits this message. - m_coordinator_up->StopCoordinator (); - m_coordinator_thread.Join (nullptr); -} - bool NativeProcessLinux::HasThreadNoLock (lldb::tid_t thread_id) { Index: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h +++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h @@ -10,10 +10,8 @@ #ifndef lldb_ThreadStateCoordinator_h #define lldb_ThreadStateCoordinator_h -#include #include #include -#include #include #include @@ -126,24 +124,9 @@ // Indicate the calling process did an exec and that the thread state // should be 100% cleared. - // - // Note this will clear out any pending notifications, but will not stop - // a notification currently in progress via ProcessNextEvent(). void ResetForExec (); - // Indicate when the coordinator should shut down. - void - StopCoordinator (); - - // Process the next event, returning false when the coordinator is all done. - // This call is synchronous and blocks when there are no events pending. - // Expected usage is to run this in a separate thread until the function - // returns false. Always call this from the same thread. The processing - // logic assumes the execution of this is implicitly serialized. - EventLoopResult - ProcessNextEvent (); - // Enable/disable verbose logging of event processing. void LogEnableEventProcessing (bool enabled); @@ -159,13 +142,10 @@ class EventThreadDeath; class EventRequestResume; - class EventStopCoordinator; class EventReset; typedef std::shared_ptr EventBaseSP; - typedef std::queue QueueType; - enum class ThreadState { Running, @@ -181,12 +161,10 @@ typedef std::unordered_map TIDContextMap; - // Private member functions. - void - EnqueueEvent (EventBaseSP event_sp); + std::mutex m_event_mutex; // Serializes execution of ProcessEvent. - EventBaseSP - DequeueEventWithWait (); + void + ProcessEvent (const EventBaseSP &event_sp); void SetPendingNotification (const EventBaseSP &event_sp); @@ -215,14 +193,6 @@ // Member variables. LogFunction m_log_function; - QueueType m_event_queue; - // For now we do simple read/write lock strategy with efficient wait-for-data. - // We can replace with an entirely non-blocking queue later but we still want the - // reader to sleep when nothing is available - this will be a bursty but infrequent - // event mechanism. - std::condition_variable m_queue_condition; - std::mutex m_queue_mutex; - EventBaseSP m_pending_notification_sp; // Maps known TIDs to ThreadContext. Index: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp +++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp @@ -46,29 +46,6 @@ //===----------------------------------------------------------------------===// -class ThreadStateCoordinator::EventStopCoordinator : public ThreadStateCoordinator::EventBase -{ -public: - EventStopCoordinator (): - EventBase () - { - } - - EventLoopResult - ProcessEvent(ThreadStateCoordinator &coordinator) override - { - return eventLoopResultStop; - } - - std::string - GetDescription () override - { - return "EventStopCoordinator"; - } -}; - -//===----------------------------------------------------------------------===// - class ThreadStateCoordinator::EventCallAfterThreadsStop : public ThreadStateCoordinator::EventBase { public: @@ -588,42 +565,12 @@ ThreadStateCoordinator::ThreadStateCoordinator (const LogFunction &log_function) : m_log_function (log_function), - m_event_queue (), - m_queue_condition (), - m_queue_mutex (), m_tid_map (), m_log_event_processing (false) { } void -ThreadStateCoordinator::EnqueueEvent (EventBaseSP event_sp) -{ - std::lock_guard lock (m_queue_mutex); - - m_event_queue.push (event_sp); - if (m_log_event_processing) - Log ("ThreadStateCoordinator::%s enqueued event: %s", __FUNCTION__, event_sp->GetDescription ().c_str ()); - - m_queue_condition.notify_one (); -} - -ThreadStateCoordinator::EventBaseSP -ThreadStateCoordinator::DequeueEventWithWait () -{ - // Wait for an event to be present. - std::unique_lock lock (m_queue_mutex); - m_queue_condition.wait (lock, - [this] { return !m_event_queue.empty (); }); - - // Grab the event and pop it off the queue. - EventBaseSP event_sp = m_event_queue.front (); - m_event_queue.pop (); - - return event_sp; -} - -void ThreadStateCoordinator::SetPendingNotification (const EventBaseSP &event_sp) { assert (event_sp && "null event_sp"); @@ -653,11 +600,11 @@ const ThreadIDFunction &call_after_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventCallAfterThreadsStop (triggering_tid, - wait_for_stop_tids, - request_thread_stop_function, - call_after_function, - error_function))); + ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid, + wait_for_stop_tids, + request_thread_stop_function, + call_after_function, + error_function))); } void @@ -666,10 +613,10 @@ const ThreadIDFunction &call_after_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventCallAfterThreadsStop (triggering_tid, - request_thread_stop_function, - call_after_function, - error_function))); + ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid, + request_thread_stop_function, + call_after_function, + error_function))); } void @@ -679,11 +626,11 @@ const ThreadIDFunction &call_after_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventCallAfterThreadsStop (triggering_tid, - request_thread_stop_function, - call_after_function, - skip_stop_request_tids, - error_function))); + ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid, + request_thread_stop_function, + call_after_function, + skip_stop_request_tids, + error_function))); } @@ -826,7 +773,7 @@ bool initiated_by_llgs, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventThreadStopped (tid, initiated_by_llgs, error_function))); + ProcessEvent(EventBaseSP(new EventThreadStopped (tid, initiated_by_llgs, error_function))); } void @@ -834,7 +781,7 @@ const ResumeThreadFunction &request_thread_resume_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, true))); + ProcessEvent(EventBaseSP(new EventRequestResume (tid, request_thread_resume_function, error_function, true))); } void @@ -842,7 +789,7 @@ const ResumeThreadFunction &request_thread_resume_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, false))); + ProcessEvent(EventBaseSP(new EventRequestResume (tid, request_thread_resume_function, error_function, false))); } void @@ -850,56 +797,26 @@ bool is_stopped, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventThreadCreate (tid, is_stopped, error_function))); + ProcessEvent(EventBaseSP(new EventThreadCreate (tid, is_stopped, error_function))); } void ThreadStateCoordinator::NotifyThreadDeath (lldb::tid_t tid, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventThreadDeath (tid, error_function))); + ProcessEvent(EventBaseSP(new EventThreadDeath (tid, error_function))); } void ThreadStateCoordinator::ResetForExec () { - std::lock_guard lock (m_queue_mutex); - - // Remove everything from the queue. This is the only - // state mutation that takes place outside the processing - // loop. - QueueType empty_queue; - m_event_queue.swap (empty_queue); - - // Do the real clear behavior on the the queue to eliminate - // the chance that processing of a dequeued earlier event is - // overlapping with the clearing of state here. Push it - // directly because we need to have this happen with the lock, - // and so far I only have this one place that needs a no-lock - // variant. - m_event_queue.push (EventBaseSP (new EventReset ())); + ProcessEvent(EventBaseSP(new EventReset())); } void -ThreadStateCoordinator::StopCoordinator () +ThreadStateCoordinator::ProcessEvent (const EventBaseSP &event_sp) { - EnqueueEvent (EventBaseSP (new EventStopCoordinator ())); -} - -ThreadStateCoordinator::EventLoopResult -ThreadStateCoordinator::ProcessNextEvent () -{ - // Dequeue the next event, synchronous. - if (m_log_event_processing) - Log ("ThreadStateCoordinator::%s about to dequeue next event in blocking mode", __FUNCTION__); - - EventBaseSP event_sp = DequeueEventWithWait(); - assert (event_sp && "event should never be null"); - if (!event_sp) - { - Log ("ThreadStateCoordinator::%s error: event_sp was null, signaling exit of event loop.", __FUNCTION__); - return eventLoopResultStop; - } + std::lock_guard lock(m_event_mutex); if (m_log_event_processing) { @@ -907,15 +824,12 @@ } // Process the event. - const EventLoopResult result = event_sp->ProcessEvent (*this); + event_sp->ProcessEvent (*this); if (m_log_event_processing) { - Log ("ThreadStateCoordinator::%s event processing returned value %s", __FUNCTION__, - result == eventLoopResultContinue ? "eventLoopResultContinue" : "eventLoopResultStop"); + Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__); } - - return result; } void Index: lldb/trunk/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp =================================================================== --- lldb/trunk/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp +++ lldb/trunk/unittests/Plugins/Process/Linux/ThreadStateCoordinatorTest.cpp @@ -22,12 +22,11 @@ // These are single-line macros so that IDE integration of gtest results puts // the error markers on the correct failure point within the gtest. -#define ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS() ASSERT_EQ (ThreadStateCoordinator::eventLoopResultContinue, m_coordinator.ProcessNextEvent ()); \ +#define ASSERT_PROCESS_EVENT_SUCCEEDED() do { \ if (HasError ()) { printf ("unexpected error in processing of event, error: %s\n", m_error_string.c_str ()); } \ -ASSERT_EQ (false, HasError ()); +ASSERT_EQ (false, HasError ()); } while(0) -#define ASSERT_PROCESS_NEXT_EVENT_FAILS() ASSERT_EQ (ThreadStateCoordinator::eventLoopResultContinue, m_coordinator.ProcessNextEvent ()); \ -ASSERT_EQ (true, HasError ()); +#define ASSERT_PROCESS_EVENT_FAILED() ASSERT_EQ (true, HasError ()) class ThreadStateCoordinatorTest: public ::testing::Test { @@ -142,14 +141,14 @@ SetupKnownRunningThread (lldb::tid_t tid) { NotifyThreadCreate (tid, false); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); } void SetupKnownStoppedThread (lldb::tid_t tid) { NotifyThreadCreate (tid, true); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); } // Convenience wrappers for ThreadStateCoordinator, using defaults for expected arguments @@ -194,13 +193,6 @@ }; } -TEST_F (ThreadStateCoordinatorTest, StopCoordinatorWorksNoPriorEvents) -{ - m_coordinator.StopCoordinator (); - ASSERT_EQ (ThreadStateCoordinator::eventLoopResultStop, m_coordinator.ProcessNextEvent ()); - ASSERT_EQ (false, HasError ()); -} - TEST_F (ThreadStateCoordinatorTest, NotifyThreadCreateSignalsErrorOnAlreadyKnownThread) { // Let the coordinator know about our thread. @@ -210,7 +202,7 @@ NotifyThreadCreate (TRIGGERING_TID, true); // This should error out. - ASSERT_PROCESS_NEXT_EVENT_FAILS (); + ASSERT_PROCESS_EVENT_FAILED (); } @@ -222,7 +214,7 @@ NotifyThreadDeath (UNKNOWN_TID); // This should error out. - ASSERT_PROCESS_NEXT_EVENT_FAILS (); + ASSERT_PROCESS_EVENT_FAILED (); } TEST_F (ThreadStateCoordinatorTest, NotifyThreadStopSignalsErrorOnUnknownThread) @@ -231,7 +223,7 @@ // Notify an unknown thread has stopped. NotifyThreadStop (UNKNOWN_TID); - ASSERT_PROCESS_NEXT_EVENT_FAILS (); + ASSERT_PROCESS_EVENT_FAILED (); } TEST_F (ThreadStateCoordinatorTest, CallAfterTheadsStopSignalsErrorOnUnknownDeferredThread) @@ -246,7 +238,7 @@ ASSERT_EQ (false, DidFireDeferredNotification ()); // Event should fail because trigger tid is unknown. - ASSERT_PROCESS_NEXT_EVENT_FAILS (); + ASSERT_PROCESS_EVENT_FAILED (); // Shouldn't have fired due to error. ASSERT_EQ (false, DidFireDeferredNotification ()); @@ -268,7 +260,7 @@ ASSERT_EQ (false, DidFireDeferredNotification ()); // Event should fail because trigger tid is unknown. - ASSERT_PROCESS_NEXT_EVENT_FAILS (); + ASSERT_PROCESS_EVENT_FAILED (); // Shouldn't have triggered deferred notification due to error. ASSERT_EQ (false, DidFireDeferredNotification ()); @@ -285,14 +277,9 @@ // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped. CallAfterThreadsStop (TRIGGERING_TID, EMPTY_THREAD_ID_SET); + ASSERT_PROCESS_EVENT_SUCCEEDED (); - // Notification trigger shouldn't go off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - - // Process next event. This will pick up the call after threads stop event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); - - // Now the trigger should have fired, since there were no threads that needed to first stop. + // The trigger should have fired, since there were no threads that needed to first stop. ASSERT_EQ (true, DidFireDeferredNotification ()); ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ()); } @@ -310,15 +297,9 @@ // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped. CallAfterThreadsStop (TRIGGERING_TID, pending_stop_tids); + ASSERT_PROCESS_EVENT_SUCCEEDED (); - // Neither trigger should have gone off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID)); - - // Process next event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); - - // Now the request thread stop should have been called for the pending stop. + // The request thread stop should have been called for the pending stop. ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID)); // But we still shouldn't have the deferred signal call go off yet. Need to wait for the stop to be reported. @@ -326,12 +307,7 @@ // Now report the that the pending stop occurred. NotifyThreadStop (PENDING_STOP_TID); - - // Shouldn't take effect until after next processing step. - ASSERT_EQ (false, DidFireDeferredNotification ()); - - // Process next event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Deferred signal notification should have fired now. ASSERT_EQ (true, DidFireDeferredNotification ()); @@ -350,15 +326,9 @@ // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped. CallAfterThreadsStop (TRIGGERING_TID, pending_stop_tids); + ASSERT_PROCESS_EVENT_SUCCEEDED (); - // Neither trigger should have gone off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - ASSERT_EQ (0u, GetRequestedStopCount ()); - - // Process next event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); - - // Now the request thread stops should have been called for the pending stop tids. + // The request thread stops should have been called for the pending stop tids. ASSERT_EQ (2u, GetRequestedStopCount ()); ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID)); ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02)); @@ -368,15 +338,14 @@ // Report the that the first pending stop occurred. NotifyThreadStop (PENDING_STOP_TID); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Shouldn't take effect until after both pending threads are notified. ASSERT_EQ (false, DidFireDeferredNotification ()); // Report the that the first pending stop occurred. NotifyThreadStop (PENDING_STOP_TID_02); - ASSERT_EQ (false, DidFireDeferredNotification ()); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Deferred signal notification should have fired now. ASSERT_EQ (true, DidFireDeferredNotification ()); @@ -393,18 +362,12 @@ // Tell m_coordinator the pending stop tid is already stopped. NotifyThreadStop (PENDING_STOP_TID); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped. CallAfterThreadsStop (TRIGGERING_TID, pending_stop_tids); - - // Neither trigger should have gone off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID)); - - // Process next event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // The pending stop should *not* fire because the m_coordinator knows it has already stopped. ASSERT_EQ (false, DidRequestStopForTid (PENDING_STOP_TID)); @@ -424,18 +387,12 @@ // Tell coordinator the pending stop tid is already stopped. NotifyThreadStop (PENDING_STOP_TID); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped. CallAfterThreadsStop (TRIGGERING_TID, pending_stop_tids); - - // Neither trigger should have gone off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - ASSERT_EQ (0u, GetRequestedStopCount ()); - - // Process next event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // The pending stop should only fire for one of the threads, the one that wasn't already stopped. ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID_02)); @@ -446,7 +403,7 @@ // Notify final thread has stopped. NotifyThreadStop (PENDING_STOP_TID_02); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // The deferred signal notification should have fired since all requirements were met. ASSERT_EQ (true, DidFireDeferredNotification ()); @@ -463,15 +420,9 @@ // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped. CallAfterThreadsStop (TRIGGERING_TID, pending_stop_tids); + ASSERT_PROCESS_EVENT_SUCCEEDED (); - // Neither trigger should have gone off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - ASSERT_EQ (0u, GetRequestedStopCount ()); - - // Process next event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); - - // Now the request thread stop should have been called for the pending stop. + // The request thread stop should have been called for the pending stop. ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID)); // But we still shouldn't have the deferred signal call go off yet. Need to wait for the death to be reported. @@ -479,12 +430,7 @@ // Now report the that the thread with pending stop dies. NotifyThreadDeath (PENDING_STOP_TID); - - // Shouldn't take effect until after next processing step. - ASSERT_EQ (false, DidFireDeferredNotification ()); - - // Process next event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Deferred signal notification should have fired now. ASSERT_EQ (true, DidFireDeferredNotification ()); @@ -501,13 +447,7 @@ // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped. CallAfterThreadsStop (TRIGGERING_TID, pending_stop_tids); - - // Neither trigger should have gone off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - ASSERT_EQ (0u, GetRequestedStopCount ()); - - // Process next event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Now the request thread stop should have been called for the pending stop. ASSERT_EQ (true, DidRequestStopForTid (PENDING_STOP_TID)); @@ -526,39 +466,18 @@ // trigger the pending notification because we should now require the // new thread to stop too. NotifyThreadStop (PENDING_STOP_TID); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); ASSERT_EQ (false, DidFireDeferredNotification ()); // Now notify the new thread stopped. NotifyThreadStop (NEW_THREAD_TID); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Deferred signal notification should have fired now. ASSERT_EQ (true, DidFireDeferredNotification ()); ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ()); } -TEST_F (ThreadStateCoordinatorTest, DeferredNotificationRemovedByResetForExec) -{ - SetupKnownStoppedThread (TRIGGERING_TID); - - // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped. - CallAfterThreadsStop (TRIGGERING_TID, - EMPTY_THREAD_ID_SET); - - // Notification trigger shouldn't go off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - - // Now indicate an exec occurred, which will invalidate all state about the process and threads. - m_coordinator.ResetForExec (); - - // Verify the deferred stop notification does *not* fire with the next - // process. It will handle the reset and not the deferred signaling, which - // should now be removed. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); - ASSERT_EQ (false, DidFireDeferredNotification ()); -} - TEST_F (ThreadStateCoordinatorTest, RequestThreadResumeSignalsErrorOnUnknownThread) { const lldb::tid_t UNKNOWN_TID = 411; @@ -574,7 +493,7 @@ ASSERT_EQ (0, resume_call_count); // Process next event. This should fail since the coordinator doesn't know about the thread. - ASSERT_PROCESS_NEXT_EVENT_FAILS (); + ASSERT_PROCESS_EVENT_FAILED (); ASSERT_EQ (0, resume_call_count); } @@ -590,11 +509,7 @@ m_coordinator.RequestThreadResume (NEW_THREAD_TID, GetResumeThreadFunction(resumed_tid, resume_call_count), GetErrorFunction ()); - // Shouldn't be called yet. - ASSERT_EQ (0, resume_call_count); - - // Process next event. After that, the resume request call should have fired. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); ASSERT_EQ (1, resume_call_count); ASSERT_EQ (NEW_THREAD_TID, resumed_tid); } @@ -611,11 +526,7 @@ m_coordinator.RequestThreadResume (NEW_THREAD_TID, GetResumeThreadFunction(resumed_tid, resume_call_count), GetErrorFunction ()); - // Shouldn't be called yet. - ASSERT_EQ (0, resume_call_count); - - // Process next event. After that, the resume request call should have fired. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); ASSERT_EQ (1, resume_call_count); ASSERT_EQ (NEW_THREAD_TID, resumed_tid); @@ -625,8 +536,8 @@ GetResumeThreadFunction(resumed_tid, resume_call_count), GetErrorFunction ()); - // Process next event. This should fail since the thread should already be running. - ASSERT_PROCESS_NEXT_EVENT_FAILS (); + // This should fail since the thread should already be running. + ASSERT_PROCESS_EVENT_FAILED (); // And the resume count should not have increased. ASSERT_EQ (initial_resume_call_count, resume_call_count); @@ -649,7 +560,7 @@ ASSERT_EQ (0, resume_call_count); // Process next event. Should be an error. - ASSERT_PROCESS_NEXT_EVENT_FAILS (); + ASSERT_PROCESS_EVENT_FAILED (); // The resume request should not have gone off because we think it is already running. ASSERT_EQ (0, resume_call_count); @@ -680,13 +591,7 @@ // Notify we have a trigger that needs to be fired when all threads in the wait tid set have stopped. CallAfterThreadsStop (TRIGGERING_TID, pending_stop_tids); - - // Neither trigger should have gone off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - ASSERT_EQ (0u, GetRequestedStopCount ()); - - // Execute CallAfterThreadsStop. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Both TID A and TID B should have had stop requests made. ASSERT_EQ (2u, GetRequestedStopCount ()); @@ -698,7 +603,7 @@ // Report thread A stopped. NotifyThreadStop (PENDING_TID_A); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); ASSERT_EQ (false, DidFireDeferredNotification ()); // Now report thread A is resuming. Ensure the resume is called. @@ -707,15 +612,13 @@ m_coordinator.RequestThreadResume (PENDING_TID_A, GetResumeThreadFunction(resumed_tid, resume_call_count), GetErrorFunction ()); - ASSERT_EQ (0, resume_call_count); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); ASSERT_EQ (1, resume_call_count); ASSERT_EQ (PENDING_TID_A, resumed_tid); // Report thread B stopped. NotifyThreadStop (PENDING_TID_B); - ASSERT_EQ (false, DidFireDeferredNotification ()); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // 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. @@ -731,14 +634,9 @@ // Notify we have a trigger that needs to be fired when all running threads have stopped. CallAfterRunningThreadsStop (TRIGGERING_TID); + ASSERT_PROCESS_EVENT_SUCCEEDED (); - // Notification trigger shouldn't go off yet. - ASSERT_EQ (false, DidFireDeferredNotification ()); - - // Process next event. This will pick up the call after threads stop event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); - - // Now the trigger should have fired, since there were no threads that needed to first stop. + // The trigger should have fired, since there were no threads that needed to first stop. ASSERT_EQ (true, DidFireDeferredNotification ()); ASSERT_EQ (TRIGGERING_TID, GetDeferredNotificationTID ()); @@ -760,7 +658,7 @@ ASSERT_EQ (false, DidFireDeferredNotification ()); // Process next event. This will pick up the call after threads stop event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // We should have two stop requests for the two threads currently running. ASSERT_EQ (2u, GetRequestedStopCount ()); @@ -772,11 +670,11 @@ // Now notify the two threads stopped. NotifyThreadStop (PENDING_STOP_TID); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); ASSERT_EQ (false, DidFireDeferredNotification ()); NotifyThreadStop (PENDING_STOP_TID_02); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Now the trigger should have fired, since there were no threads that needed to first stop. ASSERT_EQ (true, DidFireDeferredNotification ()); @@ -797,7 +695,7 @@ ASSERT_EQ (false, DidFireDeferredNotification ()); // Process next event. This will pick up the call after threads stop event. - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // We should have two stop requests for the two threads currently running. ASSERT_EQ (1u, GetRequestedStopCount ()); @@ -808,7 +706,7 @@ // Now notify the two threads stopped. NotifyThreadStop (PENDING_STOP_TID); - ASSERT_PROCESS_NEXT_EVENT_SUCCEEDS (); + ASSERT_PROCESS_EVENT_SUCCEEDED (); // Now the trigger should have fired, since there were no threads that needed to first stop. ASSERT_EQ (true, DidFireDeferredNotification ());