Implement support for restarting teams.
- TeamDebugger's listener interface now exports a TeamDebuggerRestartRequested hook. The latter is used to request starting a new debugger instance with the same arguments/settings as the team it represented. Implemented for the graphical debugger. - When a team terminates, the resulting dialog now allows the user to choose to quit, restart, or simply do nothing. The latter option still needs some work though, as e.g. setting additional breakpoints currently fails since the corresponding debugger interface is no longer around. Implements the main part of #9774.
This commit is contained in:
@@ -100,6 +100,8 @@ struct Options {
|
||||
struct DebuggedProgramInfo {
|
||||
team_id team;
|
||||
thread_id thread;
|
||||
int commandLineArgc;
|
||||
const char* const* commandLineArgv;
|
||||
bool stopInMain;
|
||||
};
|
||||
|
||||
@@ -266,6 +268,8 @@ get_debugged_program(const Options& options, DebuggedProgramInfo& _info)
|
||||
}
|
||||
printf("team: %" B_PRId32 ", thread: %" B_PRId32 "\n", team, thread);
|
||||
|
||||
_info.commandLineArgc = options.commandLineArgc;
|
||||
_info.commandLineArgv = options.commandLineArgv;
|
||||
_info.team = team;
|
||||
_info.thread = thread;
|
||||
_info.stopInMain = stopInMain;
|
||||
@@ -281,6 +285,7 @@ get_debugged_program(const Options& options, DebuggedProgramInfo& _info)
|
||||
static TeamDebugger*
|
||||
start_team_debugger(team_id teamID, SettingsManager* settingsManager,
|
||||
TeamDebugger::Listener* listener, thread_id threadID = -1,
|
||||
int commandLineArgc = 0, const char* const* commandLineArgv = NULL,
|
||||
bool stopInMain = false, UserInterface* userInterface = NULL,
|
||||
status_t* _result = NULL)
|
||||
{
|
||||
@@ -303,8 +308,10 @@ start_team_debugger(team_id teamID, SettingsManager* settingsManager,
|
||||
|
||||
TeamDebugger* debugger = new(std::nothrow) TeamDebugger(listener,
|
||||
userInterface, settingsManager);
|
||||
if (debugger)
|
||||
error = debugger->Init(teamID, threadID, stopInMain);
|
||||
if (debugger) {
|
||||
error = debugger->Init(teamID, threadID, commandLineArgc,
|
||||
commandLineArgv, stopInMain);
|
||||
}
|
||||
|
||||
if (error != B_OK) {
|
||||
printf("Error: debugger for team %" B_PRId32 " failed to init: %s!\n",
|
||||
@@ -340,6 +347,8 @@ private:
|
||||
private:
|
||||
// TeamDebugger::Listener
|
||||
virtual void TeamDebuggerStarted(TeamDebugger* debugger);
|
||||
virtual void TeamDebuggerRestartRequested(
|
||||
TeamDebugger* debugger);
|
||||
virtual void TeamDebuggerQuit(TeamDebugger* debugger);
|
||||
|
||||
virtual bool QuitRequested();
|
||||
@@ -371,6 +380,8 @@ public:
|
||||
private:
|
||||
// TeamDebugger::Listener
|
||||
virtual void TeamDebuggerStarted(TeamDebugger* debugger);
|
||||
virtual void TeamDebuggerRestartRequested(
|
||||
TeamDebugger* debugger);
|
||||
virtual void TeamDebuggerQuit(TeamDebugger* debugger);
|
||||
};
|
||||
|
||||
@@ -455,6 +466,25 @@ Debugger::MessageReceived(BMessage* message)
|
||||
message->SendReply(&reply);
|
||||
break;
|
||||
}
|
||||
case MSG_TEAM_RESTART_REQUESTED:
|
||||
{
|
||||
int32 teamID;
|
||||
if (message->FindInt32("team", &teamID) != B_OK)
|
||||
break;
|
||||
TeamDebugger* debugger = _FindTeamDebugger(teamID);
|
||||
if (debugger == NULL)
|
||||
break;
|
||||
|
||||
Options options;
|
||||
options.commandLineArgc = debugger->ArgumentCount();
|
||||
options.commandLineArgv = debugger->Arguments();
|
||||
|
||||
status_t result = _StartOrFindTeam(options);
|
||||
if (result == B_OK)
|
||||
debugger->PostMessage(B_QUIT_REQUESTED);
|
||||
|
||||
break;
|
||||
}
|
||||
case MSG_TEAM_DEBUGGER_QUIT:
|
||||
{
|
||||
int32 threadID;
|
||||
@@ -528,6 +558,15 @@ Debugger::TeamDebuggerQuit(TeamDebugger* debugger)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Debugger::TeamDebuggerRestartRequested(TeamDebugger* debugger)
|
||||
{
|
||||
BMessage message(MSG_TEAM_RESTART_REQUESTED);
|
||||
message.AddInt32("team", debugger->TeamID());
|
||||
PostMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Debugger::QuitRequested()
|
||||
{
|
||||
@@ -612,7 +651,8 @@ Debugger::_StartOrFindTeam(Options& options)
|
||||
|
||||
status_t result;
|
||||
start_team_debugger(programInfo.team, &fSettingsManager, this,
|
||||
programInfo.thread, programInfo.stopInMain, NULL, &result);
|
||||
programInfo.thread, programInfo.commandLineArgc,
|
||||
programInfo.commandLineArgv, programInfo.stopInMain, NULL, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -671,8 +711,9 @@ CliDebugger::Run(const Options& options)
|
||||
return false;
|
||||
|
||||
TeamDebugger* teamDebugger = start_team_debugger(programInfo.team,
|
||||
&settingsManager, this, programInfo.thread, programInfo.stopInMain,
|
||||
userInterface);
|
||||
&settingsManager, this, programInfo.thread,
|
||||
programInfo.commandLineArgc, programInfo.commandLineArgv,
|
||||
programInfo.stopInMain, userInterface);
|
||||
if (teamDebugger == NULL)
|
||||
return false;
|
||||
|
||||
@@ -694,6 +735,13 @@ CliDebugger::TeamDebuggerStarted(TeamDebugger* debugger)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CliDebugger::TeamDebuggerRestartRequested(TeamDebugger* debugger)
|
||||
{
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CliDebugger::TeamDebuggerQuit(TeamDebugger* debugger)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2013, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef MESSAGE_CODES_H
|
||||
@@ -48,6 +49,7 @@ enum {
|
||||
MSG_VALUE_NODE_VALUE_CHANGED = 'vnvc',
|
||||
|
||||
MSG_TEAM_DEBUGGER_QUIT = 'dbqt',
|
||||
MSG_TEAM_RESTART_REQUESTED = 'trrq',
|
||||
MSG_SHOW_TEAMS_WINDOW = 'stsw',
|
||||
MSG_TEAMS_WINDOW_CLOSED = 'tswc',
|
||||
MSG_START_NEW_TEAM = 'sttt',
|
||||
|
||||
@@ -218,7 +218,9 @@ TeamDebugger::TeamDebugger(Listener* listener, UserInterface* userInterface,
|
||||
fDebugEventListener(-1),
|
||||
fUserInterface(userInterface),
|
||||
fTerminating(false),
|
||||
fKillTeamOnQuit(false)
|
||||
fKillTeamOnQuit(false),
|
||||
fCommandLineArgc(0),
|
||||
fCommandLineArgv(NULL)
|
||||
{
|
||||
fUserInterface->AcquireReference();
|
||||
}
|
||||
@@ -293,12 +295,20 @@ TeamDebugger::~TeamDebugger()
|
||||
delete fTeam;
|
||||
delete fFileManager;
|
||||
|
||||
for (int i = 0; i < fCommandLineArgc; i++) {
|
||||
if (fCommandLineArgv[i] != NULL)
|
||||
free(const_cast<char*>(fCommandLineArgv[i]));
|
||||
}
|
||||
|
||||
delete [] fCommandLineArgv;
|
||||
|
||||
fListener->TeamDebuggerQuit(this);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
||||
TeamDebugger::Init(team_id teamID, thread_id threadID, int argc,
|
||||
const char* const* argv, bool stopInMain)
|
||||
{
|
||||
bool targetIsLocal = true;
|
||||
// TODO: Support non-local targets!
|
||||
@@ -308,12 +318,16 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
||||
|
||||
fTeamID = teamID;
|
||||
|
||||
status_t error = _HandleSetArguments(argc, argv);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// create debugger interface
|
||||
fDebuggerInterface = new(std::nothrow) DebuggerInterface(fTeamID);
|
||||
if (fDebuggerInterface == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = fDebuggerInterface->Init();
|
||||
error = fDebuggerInterface->Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@@ -717,6 +731,25 @@ TeamDebugger::MessageReceived(BMessage* message)
|
||||
Activate();
|
||||
break;
|
||||
|
||||
case MSG_TEAM_RESTART_REQUESTED:
|
||||
{
|
||||
if (fCommandLineArgc == 0)
|
||||
break;
|
||||
|
||||
BString argumentString;
|
||||
for (int i = 0; i < fCommandLineArgc; i++) {
|
||||
if (i > 0)
|
||||
argumentString.Append(" ");
|
||||
argumentString.Append(fCommandLineArgv[i]);
|
||||
}
|
||||
|
||||
BMessage startMessage(MSG_START_NEW_TEAM);
|
||||
startMessage.AddString("path", fCommandLineArgv[0]);
|
||||
startMessage.AddString("arguments", argumentString);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BLooper::MessageReceived(message);
|
||||
break;
|
||||
@@ -1240,11 +1273,19 @@ bool
|
||||
TeamDebugger::_HandleTeamDeleted(TeamDeletedEvent* event)
|
||||
{
|
||||
char message[64];
|
||||
snprintf(message, sizeof(message), "Team %" B_PRId32 " has terminated.",
|
||||
snprintf(message, sizeof(message), "Team %" B_PRId32 " has terminated. ",
|
||||
event->Team());
|
||||
fUserInterface->SynchronouslyAskUser("Quit Debugger", message, "Quit",
|
||||
NULL, NULL);
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
|
||||
int32 result = fUserInterface->SynchronouslyAskUser("Team terminated",
|
||||
message, "Do nothing", "Quit", fCommandLineArgc != 0
|
||||
? "Restart team" : NULL);
|
||||
|
||||
if (result == 1)
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
else if (result == 2) {
|
||||
_SaveSettings();
|
||||
fListener->TeamDebuggerRestartRequested(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1658,6 +1699,26 @@ TeamDebugger::_HandleInspectAddress(target_addr_t address,
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TeamDebugger::_HandleSetArguments(int argc, const char* const* argv)
|
||||
{
|
||||
fCommandLineArgc = argc;
|
||||
fCommandLineArgv = new(std::nothrow) const char*[argc];
|
||||
if (fCommandLineArgv == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(const_cast<char **>(fCommandLineArgv), 0, sizeof(char*) * argc);
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
fCommandLineArgv[i] = strdup(argv[i]);
|
||||
if (fCommandLineArgv[i] == NULL)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
ThreadHandler*
|
||||
TeamDebugger::_GetThreadHandler(thread_id threadID)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TEAM_DEBUGGER_H
|
||||
@@ -40,12 +41,19 @@ public:
|
||||
~TeamDebugger();
|
||||
|
||||
status_t Init(team_id teamID, thread_id threadID,
|
||||
int argc,
|
||||
const char* const* argv,
|
||||
bool stopInMain);
|
||||
|
||||
void Activate();
|
||||
|
||||
team_id TeamID() const { return fTeamID; }
|
||||
|
||||
int ArgumentCount() const
|
||||
{ return fCommandLineArgc; }
|
||||
const char** Arguments() const
|
||||
{ return fCommandLineArgv; }
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
@@ -153,6 +161,8 @@ private:
|
||||
void _HandleInspectAddress(
|
||||
target_addr_t address,
|
||||
TeamMemoryBlock::Listener* listener);
|
||||
status_t _HandleSetArguments(int argc,
|
||||
const char* const* argv);
|
||||
|
||||
ThreadHandler* _GetThreadHandler(thread_id threadID);
|
||||
|
||||
@@ -189,6 +199,8 @@ private:
|
||||
volatile bool fTerminating;
|
||||
bool fKillTeamOnQuit;
|
||||
TeamSettings fTeamSettings;
|
||||
int fCommandLineArgc;
|
||||
const char** fCommandLineArgv;
|
||||
};
|
||||
|
||||
|
||||
@@ -197,6 +209,8 @@ public:
|
||||
virtual ~Listener();
|
||||
|
||||
virtual void TeamDebuggerStarted(TeamDebugger* debugger) = 0;
|
||||
virtual void TeamDebuggerRestartRequested(
|
||||
TeamDebugger* debugger) = 0;
|
||||
virtual void TeamDebuggerQuit(TeamDebugger* debugger) = 0;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user