[haiku-commits] haiku: hrev44371 - in src/apps/debugger: . user_interface/cli

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 21 Jul 2012 09:20:17 +0200 (CEST)

hrev44371 adds 1 changeset to branch 'master'
old head: 5ba5e31f8a59cb5f3299edd7af256d0fb4db12aa
new head: 0a592099a94eb3727053c0e2ca571398dff75701

----------------------------------------------------------------------------

0a59209: Debugger: Rework CLI setup to no longer create a BApplication
  
  The main thread does now serve the CLI input loop.

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev44371
Commit:      0a592099a94eb3727053c0e2ca571398dff75701
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0a59209
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Jul 21 07:18:34 2012 UTC

----------------------------------------------------------------------------

3 files changed, 245 insertions(+), 69 deletions(-)
src/apps/debugger/Debugger.cpp                     |  259 ++++++++++++----
.../cli/CommandLineUserInterface.cpp               |   47 ++-
.../user_interface/cli/CommandLineUserInterface.h  |    8 +-

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/Debugger.cpp b/src/apps/debugger/Debugger.cpp
index f561747..bac8ac0 100644
--- a/src/apps/debugger/Debugger.cpp
+++ b/src/apps/debugger/Debugger.cpp
@@ -88,6 +88,13 @@ struct Options {
 };
 
 
+struct DebuggedProgramInfo {
+       team_id         team;
+       thread_id       thread;
+       bool            stopInMain;
+};
+
+
 static bool
 parse_arguments(int argc, const char* const* argv, bool noOutput,
        Options& options)
@@ -174,25 +181,104 @@ parse_arguments(int argc, const char* const* argv, bool 
noOutput,
        return true;
 }
 
+static status_t
+global_init()
+{
+       status_t error = TypeHandlerRoster::CreateDefault();
+       if (error != B_OK)
+               return error;
+
+       error = ValueHandlerRoster::CreateDefault();
+       if (error != B_OK)
+               return error;
+
+       return B_OK;
+}
+
+
+/**
+ * Finds or runs the program to debug, depending on the command line options.
+ * @param options The parsed command line options.
+ * @param _info The info for the program to fill in. Will only be filled in
+ *               if successful.
+ * @return \c true, if the program has been found or ran.
+ */
+static bool
+get_debugged_program(const Options& options, DebuggedProgramInfo& _info)
+{
+       team_id team = options.team;
+       thread_id thread = options.thread;
+       bool stopInMain = false;
+
+       // If command line arguments were given, start the program.
+       if (options.commandLineArgc > 0) {
+               printf("loading program: \"%s\" ...\n", 
options.commandLineArgv[0]);
+               // TODO: What about the CWD?
+               thread = load_program(options.commandLineArgv,
+                       options.commandLineArgc, false);
+               if (thread < 0) {
+                       // TODO: Notify the user!
+                       fprintf(stderr, "Error: Failed to load program \"%s\": 
%s\n",
+                               options.commandLineArgv[0], strerror(thread));
+                       return false;
+               }
+
+               team = thread;
+                       // main thread ID == team ID
+               stopInMain = true;
+       }
 
+       // no parameters given, prompt the user to attach to a team
+       if (team < 0 && thread < 0)
+               return false;
+
+       // no team, but a thread -- get team
+       if (team < 0) {
+               printf("no team yet, getting thread info...\n");
+               thread_info threadInfo;
+               status_t error = get_thread_info(thread, &threadInfo);
+               if (error != B_OK) {
+                       // TODO: Notify the user!
+                       fprintf(stderr, "Error: Failed to get info for thread 
\"%ld\": "
+                               "%s\n", thread, strerror(error));
+                       return false;
+               }
+
+               team = threadInfo.team;
+       }
+       printf("team: %ld, thread: %ld\n", team, thread);
+
+       _info.team = team;
+       _info.thread = thread;
+       _info.stopInMain = stopInMain;
+       return true;
+}
+
+
+/**
+ * Creates a TeamDebugger for the given team. If userInterface is given,
+ * that user interface is used (the caller retains its reference), otherwise
+ * a graphical user interface is created.
+ */
 static TeamDebugger*
 start_team_debugger(team_id teamID, SettingsManager* settingsManager,
        TeamDebugger::Listener* listener, thread_id threadID = -1,
-       bool stopInMain = false, bool useCLI = false)
+       bool stopInMain = false, UserInterface* userInterface = NULL)
 {
        if (teamID < 0)
                return NULL;
 
-       UserInterface* userInterface = useCLI
-               ? (UserInterface*)new(std::nothrow)     CommandLineUserInterface
-               : (UserInterface*)new(std::nothrow)     GraphicalUserInterface;
-
+       BReference<UserInterface> userInterfaceReference;
        if (userInterface == NULL) {
-               // TODO: Notify the user!
-               fprintf(stderr, "Error: Out of memory!\n");
-               return NULL;
+               userInterface = new(std::nothrow) GraphicalUserInterface;
+               if (userInterface == NULL) {
+                       // TODO: Notify the user!
+                       fprintf(stderr, "Error: Out of memory!\n");
+                       return NULL;
+               }
+
+               userInterfaceReference.SetTo(userInterface, true);
        }
-       BReference<UserInterface> userInterfaceReference(userInterface, true);
 
        status_t error = B_NO_MEMORY;
 
@@ -213,6 +299,7 @@ start_team_debugger(team_id teamID, SettingsManager* 
settingsManager,
        return debugger;
 }
 
+
 // #pragma mark - Debugger application class
 
 
@@ -247,6 +334,26 @@ private:
 };
 
 
+// #pragma mark - CliDebugger
+
+
+class CliDebugger : private TeamDebugger::Listener {
+public:
+                                                               CliDebugger();
+                                                               ~CliDebugger();
+
+                       bool                            Run(const Options& 
options);
+
+private:
+       // TeamDebugger::Listener
+       virtual void                            
TeamDebuggerStarted(TeamDebugger* debugger);
+       virtual void                            TeamDebuggerQuit(TeamDebugger* 
debugger);
+};
+
+
+// #pragma mark - Debugger application class
+
+
 Debugger::Debugger()
        :
        BApplication(kDebuggerSignature),
@@ -266,11 +373,7 @@ Debugger::~Debugger()
 status_t
 Debugger::Init()
 {
-       status_t error = TypeHandlerRoster::CreateDefault();
-       if (error != B_OK)
-               return error;
-
-       error = ValueHandlerRoster::CreateDefault();
+       status_t error = global_init();
        if (error != B_OK)
                return error;
 
@@ -348,63 +451,22 @@ Debugger::ArgvReceived(int32 argc, char** argv)
                return;
        }
 
-       team_id team = options.team;
-       thread_id thread = options.thread;
-       bool stopInMain = false;
-
-       // If command line arguments were given, start the program.
-       if (options.commandLineArgc > 0) {
-               printf("loading program: \"%s\" ...\n", 
options.commandLineArgv[0]);
-               // TODO: What about the CWD?
-               thread = load_program(options.commandLineArgv,
-                       options.commandLineArgc, false);
-               if (thread < 0) {
-                       // TODO: Notify the user!
-                       fprintf(stderr, "Error: Failed to load program \"%s\": 
%s\n",
-                               options.commandLineArgv[0], strerror(thread));
-                       return;
-               }
-
-               team = thread;
-                       // main thread ID == team ID
-               stopInMain = true;
-       }
-
-       // no parameters given, prompt the user to attach to a team
-       if (team < 0 && thread < 0)
+       DebuggedProgramInfo programInfo;
+       if (!get_debugged_program(options, programInfo))
                return;
 
-       // If we've got
-       if (team < 0) {
-               printf("no team yet, getting thread info...\n");
-               thread_info threadInfo;
-               status_t error = get_thread_info(thread, &threadInfo);
-               if (error != B_OK) {
-                       // TODO: Notify the user!
-                       fprintf(stderr, "Error: Failed to get info for thread 
\"%ld\": "
-                               "%s\n", thread, strerror(error));
-                       return;
-               }
-
-               team = threadInfo.team;
-       }
-       printf("team: %ld, thread: %ld\n", team, thread);
-
-       TeamDebugger* debugger = _FindTeamDebugger(team);
+       TeamDebugger* debugger = _FindTeamDebugger(programInfo.team);
        if (debugger != NULL) {
-               printf("There's already a debugger for team: %ld\n", team);
+               printf("There's already a debugger for team: %ld\n", 
programInfo.team);
                debugger->Activate();
                return;
        }
 
-       start_team_debugger(team, &fSettingsManager, this, thread, stopInMain,
-               options.useCLI);
+       start_team_debugger(programInfo.team, &fSettingsManager, this,
+               programInfo.thread, programInfo.stopInMain);
 }
 
 
-// TeamDebugger::Listener
-
-
 void
 Debugger::TeamDebuggerStarted(TeamDebugger* debugger)
 {
@@ -480,6 +542,76 @@ Debugger::_FindTeamDebugger(team_id teamID) const
 }
 
 
+// #pragma mark - CliDebugger
+
+
+CliDebugger::CliDebugger()
+{
+}
+
+
+CliDebugger::~CliDebugger()
+{
+}
+
+
+bool
+CliDebugger::Run(const Options& options)
+{
+       // initialize global objects and settings manager
+       status_t error = global_init();
+       if (error != B_OK) {
+               fprintf(stderr, "Error: Global initialization failed: %s\n",
+                       strerror(error));
+               return false;
+       }
+
+       SettingsManager settingsManager;
+       error = settingsManager.Init();
+       if (error != B_OK) {
+               fprintf(stderr, "Error: Settings manager initialization failed: 
"
+                       "%s\n", strerror(error));
+               return false;
+       }
+
+       // create the command line UI
+       CommandLineUserInterface* userInterface
+               = new(std::nothrow) CommandLineUserInterface;
+       if (userInterface == NULL) {
+               fprintf(stderr, "Error: Out of memory!\n");
+               return false;
+       }
+       BReference<UserInterface> userInterfaceReference(userInterface, true);
+
+       // get/run the program to be debugged and start the team debugger
+       DebuggedProgramInfo programInfo;
+       if (!get_debugged_program(options, programInfo))
+               return false;
+
+       if (start_team_debugger(programInfo.team, &settingsManager, this,
+                       programInfo.thread, programInfo.stopInMain, 
userInterface)
+                       == NULL) {
+               return false;
+       }
+
+       userInterface->Run();
+
+       return true;
+}
+
+
+void
+CliDebugger::TeamDebuggerStarted(TeamDebugger* debugger)
+{
+}
+
+
+void
+CliDebugger::TeamDebuggerQuit(TeamDebugger* debugger)
+{
+}
+
+
 // #pragma mark -
 
 
@@ -495,6 +627,11 @@ main(int argc, const char* const* argv)
        Options options;
        parse_arguments(argc, argv, false, options);
 
+       if (options.useCLI) {
+               CliDebugger debugger;
+               return debugger.Run(options) ? 0 : 1;
+       }
+
        Debugger app;
        status_t error = app.Init();
        if (error != B_OK) {
diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp 
b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
index ab53011..09db85f 100644
--- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
+++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp
@@ -96,10 +96,11 @@ private:
 
 CommandLineUserInterface::CommandLineUserInterface()
        :
-       fThread(-1),
        fTeam(NULL),
        fListener(NULL),
        fCommands(20, true),
+       fShowSemaphore(-1),
+       fShown(false),
        fTerminating(false)
 {
 }
@@ -107,6 +108,8 @@ CommandLineUserInterface::CommandLineUserInterface()
 
 CommandLineUserInterface::~CommandLineUserInterface()
 {
+       if (fShowSemaphore >= 0)
+               delete_sem(fShowSemaphore);
 }
 
 
@@ -127,9 +130,9 @@ CommandLineUserInterface::Init(Team* team, 
UserInterfaceListener* listener)
        if (error != B_OK)
                return error;
 
-       fThread = spawn_thread(&_InputLoopEntry, "CLI", B_NORMAL_PRIORITY, 
this);
-       if (fThread < 0)
-               return fThread;
+       fShowSemaphore = create_sem(0, "show CLI");
+       if (fShowSemaphore < 0)
+               return fShowSemaphore;
 
        return B_OK;
 }
@@ -138,7 +141,8 @@ CommandLineUserInterface::Init(Team* team, 
UserInterfaceListener* listener)
 void
 CommandLineUserInterface::Show()
 {
-       resume_thread(fThread);
+       fShown = true;
+       release_sem(fShowSemaphore);
 }
 
 
@@ -146,8 +150,18 @@ void
 CommandLineUserInterface::Terminate()
 {
        fTerminating = true;
-       // TODO: Signal the thread so it wakes up!
-       wait_for_thread(fThread, NULL);
+
+       if (fShown) {
+               // TODO: Signal the thread so it wakes up!
+
+               // Wait for input loop to finish.
+               while (acquire_sem(fShowSemaphore) == B_INTERRUPTED) {
+               }
+       } else {
+               // The main thread will still be blocked in Run(). Unblock it.
+               delete_sem(fShowSemaphore);
+               fShowSemaphore = -1;
+       }
 }
 
 
@@ -181,6 +195,25 @@ CommandLineUserInterface::SynchronouslyAskUser(const char* 
title,
 }
 
 
+void
+CommandLineUserInterface::Run()
+{
+       // Wait for the Show() semaphore to be released.
+       status_t error;
+       do {
+               error = acquire_sem(fShowSemaphore);
+       } while (error == B_INTERRUPTED);
+
+       if (error != B_OK)
+               return;
+
+       _InputLoop();
+
+       // Release the Show() semaphore to signal Terminate().
+       release_sem(fShowSemaphore);
+}
+
+
 /*static*/ status_t
 CommandLineUserInterface::_InputLoopEntry(void* data)
 {
diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h 
b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h
index b581f36..9d0c071 100644
--- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h
+++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h
@@ -40,6 +40,11 @@ public:
                                                                        const 
char* message, const char* choice1,
                                                                        const 
char* choice2, const char* choice3);
 
+                       void                            Run();
+                                                                       // 
Called by the main thread, when
+                                                                       // 
everything has been set up. Enters the
+                                                                       // 
input loop.
+
 private:
                        struct CommandEntry;
                        typedef BObjectList<CommandEntry> CommandList;
@@ -63,10 +68,11 @@ private:
                        void                            _PrintHelp();
 
 private:
-                       thread_id                       fThread;
                        Team*                           fTeam;
                        UserInterfaceListener* fListener;
                        CommandList                     fCommands;
+                       sem_id                          fShowSemaphore;
+                       bool                            fShown;
                        bool                            fTerminating;
 };
 


Other related posts:

  • » [haiku-commits] haiku: hrev44371 - in src/apps/debugger: . user_interface/cli - ingo_weinhold