hrev44423 adds 3 changesets to branch 'master' old head: e51854a127450ed5f1dc33ec350a00f1deaff355 new head: d266c87d174fc714e2c0ecbfe9c18713f3c9215d ---------------------------------------------------------------------------- 726d557: Debugger CLI: Wait for TeamDebugger thread to die before exit() 4d8eaa5: Debugger: UserInterface.h: style cleanup d266c87: Debugger: CliContext: Introduce the notion of events * The input loop can now wait on abstract events, which other threads (or even the input loop thread itself) can signal. * Use the new mechanism in QuitSession(). * Also (with the exception of the SIGINT part) implement WaitForThreadOrUser(). [ Ingo Weinhold <ingo_weinhold@xxxxxx> ] ---------------------------------------------------------------------------- 4 files changed, 136 insertions(+), 26 deletions(-) src/apps/debugger/Debugger.cpp | 14 +- src/apps/debugger/user_interface/UserInterface.h | 10 +- .../debugger/user_interface/cli/CliContext.cpp | 116 +++++++++++++--- src/apps/debugger/user_interface/cli/CliContext.h | 22 ++- ############################################################################ Commit: 726d557c9e2cedcf3145146e3e054c4931c5cb1e URL: http://cgit.haiku-os.org/haiku/commit/?id=726d557 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sat Jul 28 22:18:12 2012 UTC Debugger CLI: Wait for TeamDebugger thread to die before exit() ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/Debugger.cpp b/src/apps/debugger/Debugger.cpp index 888db4a..645151d 100644 --- a/src/apps/debugger/Debugger.cpp +++ b/src/apps/debugger/Debugger.cpp @@ -594,14 +594,20 @@ CliDebugger::Run(const Options& options) if (!get_debugged_program(options, programInfo)) return false; - if (start_team_debugger(programInfo.team, &settingsManager, this, - programInfo.thread, programInfo.stopInMain, userInterface) - == NULL) { + TeamDebugger* teamDebugger = start_team_debugger(programInfo.team, + &settingsManager, this, programInfo.thread, programInfo.stopInMain, + userInterface); + if (teamDebugger == NULL) return false; - } + thread_id teamDebuggerThread = teamDebugger->Thread(); + + // run the input loop userInterface->Run(); + // wait for the team debugger thread to terminate + wait_for_thread(teamDebuggerThread, NULL); + return true; } ############################################################################ Commit: 4d8eaa5b11b21e3913b6937e298a7370c3e8c4f8 URL: http://cgit.haiku-os.org/haiku/commit/?id=4d8eaa5 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sat Jul 28 22:18:43 2012 UTC Debugger: UserInterface.h: style cleanup ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index 2f69266..60ae097 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -68,11 +68,11 @@ public: class UserInterfaceListener { public: - enum QuitOption { - QUIT_OPTION_ASK_USER, - QUIT_OPTION_ASK_KILL_TEAM, - QUIT_OPTION_ASK_RESUME_TEAM - }; + enum QuitOption { + QUIT_OPTION_ASK_USER, + QUIT_OPTION_ASK_KILL_TEAM, + QUIT_OPTION_ASK_RESUME_TEAM + }; public: virtual ~UserInterfaceListener(); ############################################################################ Revision: hrev44423 Commit: d266c87d174fc714e2c0ecbfe9c18713f3c9215d URL: http://cgit.haiku-os.org/haiku/commit/?id=d266c87 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sat Jul 28 22:28:11 2012 UTC Debugger: CliContext: Introduce the notion of events * The input loop can now wait on abstract events, which other threads (or even the input loop thread itself) can signal. * Use the new mechanism in QuitSession(). * Also (with the exception of the SIGINT part) implement WaitForThreadOrUser(). ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp index ad14f82..68b8e77 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.cpp +++ b/src/apps/debugger/user_interface/cli/CliContext.cpp @@ -28,16 +28,22 @@ CliContext::CliContext() fHistory(NULL), fPrompt(NULL), fBlockingSemaphore(-1), + fInputLoopWaitingForEvents(0), + fEventsOccurred(0), fInputLoopWaiting(false), fTerminating(false) { sCurrentContext = this; } + CliContext::~CliContext() { Cleanup(); sCurrentContext = NULL; + + if (fBlockingSemaphore >= 0) + delete_sem(fBlockingSemaphore); } @@ -47,6 +53,8 @@ CliContext::Init(Team* team, UserInterfaceListener* listener) fTeam = team; fListener = listener; + fTeam->AddListener(this); + status_t error = fLock.InitCheck(); if (error != B_OK) return error; @@ -88,6 +96,11 @@ CliContext::Cleanup() history_end(fHistory); fHistory = NULL; } + + if (fTeam != NULL) { + fTeam->RemoveListener(this); + fTeam = NULL; + } } @@ -97,13 +110,7 @@ CliContext::Terminating() AutoLocker<BLocker> locker(fLock); fTerminating = true; - - if (fBlockingSemaphore >= 0) { - delete_sem(fBlockingSemaphore); - fBlockingSemaphore = -1; - } - - fInputLoopWaiting = false; + _SignalInputLoop(EVENT_QUIT); // TODO: Signal the input loop, should it be in PromptUser()! } @@ -134,27 +141,104 @@ CliContext::AddLineToInputHistory(const char* line) void CliContext::QuitSession(bool killTeam) { - AutoLocker<BLocker> locker(fLock); - - sem_id blockingSemaphore = fBlockingSemaphore; - fInputLoopWaiting = true; - - locker.Unlock(); + _PrepareToWaitForEvents(EVENT_QUIT); fListener->UserInterfaceQuitRequested( killTeam ? UserInterfaceListener::QUIT_OPTION_ASK_KILL_TEAM : UserInterfaceListener::QUIT_OPTION_ASK_RESUME_TEAM); - while (acquire_sem(blockingSemaphore) == B_INTERRUPTED) { - } + _WaitForEvents(); } void CliContext::WaitForThreadOrUser() { - // TODO:... +// TODO: Deal with SIGINT as well! + for (;;) { + _PrepareToWaitForEvents( + EVENT_USER_INTERRUPT | EVENT_THREAD_STATE_CHANGED); + + // check whether there are any threads stopped already + thread_id stoppedThread = -1; + AutoLocker<Team> teamLocker(fTeam); + + for (ThreadList::ConstIterator it = fTeam->Threads().GetIterator(); + Thread* thread = it.Next();) { + if (thread->State() == THREAD_STATE_STOPPED) { + stoppedThread = thread->ID(); + break; + } + } + + teamLocker.Unlock(); + + if (stoppedThread >= 0) + _SignalInputLoop(EVENT_THREAD_STATE_CHANGED); + + uint32 events = _WaitForEvents(); + if ((events & EVENT_QUIT) != 0 || stoppedThread >= 0) + return; + } +} + + +void +CliContext::ThreadStateChanged(const Team::ThreadEvent& event) +{ + _SignalInputLoop(EVENT_THREAD_STATE_CHANGED); +} + + +void +CliContext::_PrepareToWaitForEvents(uint32 eventMask) +{ + // Set the events we're going to wait for -- always wait for "quit". + AutoLocker<BLocker> locker(fLock); + fInputLoopWaitingForEvents = eventMask | EVENT_QUIT; + fEventsOccurred = fTerminating ? EVENT_QUIT : 0; +} + + +uint32 +CliContext::_WaitForEvents() +{ + AutoLocker<BLocker> locker(fLock); + + if (fEventsOccurred == 0) { + sem_id blockingSemaphore = fBlockingSemaphore; + fInputLoopWaiting = true; + + locker.Unlock(); + + while (acquire_sem(blockingSemaphore) == B_INTERRUPTED) { + } + + locker.Lock(); + } + + uint32 events = fEventsOccurred; + fEventsOccurred = 0; + return events; +} + + +void +CliContext::_SignalInputLoop(uint32 events) +{ + AutoLocker<BLocker> locker(fLock); + + if ((fInputLoopWaitingForEvents & events) == 0) + return; + + fEventsOccurred = fInputLoopWaitingForEvents & events; + fInputLoopWaitingForEvents = 0; + + if (fInputLoopWaiting) { + fInputLoopWaiting = false; + release_sem(fBlockingSemaphore); + } } diff --git a/src/apps/debugger/user_interface/cli/CliContext.h b/src/apps/debugger/user_interface/cli/CliContext.h index e3617fe..0d5771e 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.h +++ b/src/apps/debugger/user_interface/cli/CliContext.h @@ -12,12 +12,21 @@ #include <Locker.h> +#include "Team.h" + class Team; class UserInterfaceListener; -class CliContext { +class CliContext : private Team::Listener { +public: + enum { + EVENT_QUIT = 0x01, + EVENT_USER_INTERRUPT = 0x02, + EVENT_THREAD_STATE_CHANGED = 0x04, + }; + public: CliContext(); ~CliContext(); @@ -40,6 +49,15 @@ public: void WaitForThreadOrUser(); private: + // Team::Listener + virtual void ThreadStateChanged( + const Team::ThreadEvent& event); + +private: + void _PrepareToWaitForEvents(uint32 eventMask); + uint32 _WaitForEvents(); + void _SignalInputLoop(uint32 events); + static const char* _GetPrompt(EditLine* editLine); private: @@ -50,6 +68,8 @@ private: History* fHistory; const char* fPrompt; sem_id fBlockingSemaphore; + uint32 fInputLoopWaitingForEvents; + uint32 fEventsOccurred; bool fInputLoopWaiting; volatile bool fTerminating; };