Allow saving a crash report from debug_server.
- When debug_server is built to use the graphical debugger as its crash handler, also present the option to save a report instead of debugging the app. Doesn't work 100% correctly yet though since the report generator needs to wait for stack traces to be generated if they aren't yet ready.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011, Rene Gollent, [email protected].
|
* Copyright 2011-2012, Rene Gollent, [email protected].
|
||||||
* Copyright 2005-2009, Ingo Weinhold, [email protected].
|
* Copyright 2005-2009, Ingo Weinhold, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +34,13 @@
|
|||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kActionKillTeam,
|
||||||
|
kActionDebugTeam,
|
||||||
|
kActionSaveReportTeam
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define HANDOVER_USE_GDB 1
|
#define HANDOVER_USE_GDB 1
|
||||||
//#define HANDOVER_USE_DEBUGGER 1
|
//#define HANDOVER_USE_DEBUGGER 1
|
||||||
|
|
||||||
@@ -118,11 +125,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
status_t _PopMessage(DebugMessage *&message);
|
status_t _PopMessage(DebugMessage *&message);
|
||||||
|
|
||||||
thread_id _EnterDebugger();
|
thread_id _EnterDebugger(bool saveReport);
|
||||||
status_t _SetupGDBArguments(BStringList &arguments, bool usingConsoled);
|
status_t _SetupGDBArguments(BStringList &arguments, bool usingConsoled);
|
||||||
void _KillTeam();
|
void _KillTeam();
|
||||||
|
|
||||||
bool _HandleMessage(DebugMessage *message);
|
int32 _HandleMessage(DebugMessage *message);
|
||||||
|
|
||||||
void _LookupSymbolAddress(debug_symbol_lookup_context *lookupContext,
|
void _LookupSymbolAddress(debug_symbol_lookup_context *lookupContext,
|
||||||
const void *address, char *buffer, int32 bufferSize);
|
const void *address, char *buffer, int32 bufferSize);
|
||||||
@@ -512,7 +519,7 @@ TeamDebugHandler::_SetupGDBArguments(BStringList &arguments, bool usingConsoled)
|
|||||||
|
|
||||||
|
|
||||||
thread_id
|
thread_id
|
||||||
TeamDebugHandler::_EnterDebugger()
|
TeamDebugHandler::_EnterDebugger(bool saveReport)
|
||||||
{
|
{
|
||||||
TRACE(("debug_server: TeamDebugHandler::_EnterDebugger(): team %" B_PRId32
|
TRACE(("debug_server: TeamDebugHandler::_EnterDebugger(): team %" B_PRId32
|
||||||
"\n", fTeam));
|
"\n", fTeam));
|
||||||
@@ -575,6 +582,10 @@ TeamDebugHandler::_EnterDebugger()
|
|||||||
|
|
||||||
BString debuggerParam;
|
BString debuggerParam;
|
||||||
debuggerParam.SetToFormat("%" B_PRId32, fTeam);
|
debuggerParam.SetToFormat("%" B_PRId32, fTeam);
|
||||||
|
if (saveReport) {
|
||||||
|
if (!arguments.Add("--save-report"))
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
if (!arguments.Add("--team") || !arguments.Add(debuggerParam))
|
if (!arguments.Add("--team") || !arguments.Add(debuggerParam))
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -610,7 +621,7 @@ TeamDebugHandler::_KillTeam()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
int32
|
||||||
TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
||||||
{
|
{
|
||||||
// This method is called only for the first message the debugger gets for
|
// This method is called only for the first message the debugger gets for
|
||||||
@@ -669,12 +680,12 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
|||||||
|
|
||||||
_PrintStackTrace(thread);
|
_PrintStackTrace(thread);
|
||||||
|
|
||||||
bool kill = true;
|
int32 debugAction = kActionKillTeam;
|
||||||
|
|
||||||
// ask the user whether to debug or kill the team
|
// ask the user whether to debug or kill the team
|
||||||
if (_IsGUIServer()) {
|
if (_IsGUIServer()) {
|
||||||
// App server, input server, or registrar. We always debug those.
|
// App server, input server, or registrar. We always debug those.
|
||||||
kill = false;
|
debugAction = kActionDebugTeam;
|
||||||
} else if (USE_GUI && _AreGUIServersAlive() && _InitGUI() == B_OK) {
|
} else if (USE_GUI && _AreGUIServersAlive() && _InitGUI() == B_OK) {
|
||||||
// normal app -- tell the user
|
// normal app -- tell the user
|
||||||
_NotifyAppServer(fTeam);
|
_NotifyAppServer(fTeam);
|
||||||
@@ -688,16 +699,24 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
|||||||
|
|
||||||
// TODO: It would be nice if the alert would go away automatically
|
// TODO: It would be nice if the alert would go away automatically
|
||||||
// if someone else kills our teams.
|
// if someone else kills our teams.
|
||||||
|
#ifdef HANDOVER_USE_DEBUGGER
|
||||||
BAlert *alert = new BAlert(NULL, buffer.String(),
|
BAlert *alert = new BAlert(NULL, buffer.String(),
|
||||||
B_TRANSLATE("Debug"), B_TRANSLATE("OK"), NULL,
|
B_TRANSLATE("Terminate"), B_TRANSLATE("Debug"),
|
||||||
|
B_TRANSLATE("Save Report"), B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
||||||
|
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
||||||
|
debugAction = alert->Go();
|
||||||
|
_NotifyRegistrar(fTeam, false, debugAction != kActionKillTeam);
|
||||||
|
#else
|
||||||
|
BAlert *alert = new BAlert(NULL, buffer.String(),
|
||||||
|
B_TRANSLATE("Kill"), B_TRANSLATE("Debug"), NULL,
|
||||||
B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
B_WIDTH_AS_USUAL, B_WARNING_ALERT);
|
||||||
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
||||||
int32 result = alert->Go();
|
debugAction = alert->Go();
|
||||||
kill = (result == 1);
|
_NotifyRegistrar(fTeam, false, debugAction != kActionKillTeam);
|
||||||
_NotifyRegistrar(fTeam, false, !kill);
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return kill;
|
return debugAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -858,26 +877,26 @@ TeamDebugHandler::_HandlerThread()
|
|||||||
|
|
||||||
DebugMessage *message;
|
DebugMessage *message;
|
||||||
status_t error = _PopMessage(message);
|
status_t error = _PopMessage(message);
|
||||||
bool kill;
|
int32 debugAction = kActionKillTeam;
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
// handle the message
|
// handle the message
|
||||||
kill = _HandleMessage(message);
|
debugAction = _HandleMessage(message);
|
||||||
delete message;
|
delete message;
|
||||||
} else {
|
} else {
|
||||||
debug_printf("TeamDebugHandler::_HandlerThread(): Failed to pop "
|
debug_printf("TeamDebugHandler::_HandlerThread(): Failed to pop "
|
||||||
"initial message: %s", strerror(error));
|
"initial message: %s", strerror(error));
|
||||||
kill = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isGuiServer = _IsGUIServer();
|
bool isGuiServer = _IsGUIServer();
|
||||||
|
|
||||||
// kill the team or hand it over to the debugger
|
// kill the team or hand it over to the debugger
|
||||||
thread_id debuggerThread = -1;
|
thread_id debuggerThread = -1;
|
||||||
if (kill) {
|
if (debugAction == kActionKillTeam) {
|
||||||
// The team shall be killed. Since that is also the handling in case
|
// The team shall be killed. Since that is also the handling in case
|
||||||
// an error occurs while handing over the team to the debugger, we do
|
// an error occurs while handing over the team to the debugger, we do
|
||||||
// nothing here.
|
// nothing here.
|
||||||
} else if ((debuggerThread = _EnterDebugger()) >= 0) {
|
} else if ((debuggerThread = _EnterDebugger(
|
||||||
|
debugAction == kActionSaveReportTeam)) >= 0) {
|
||||||
// wait for the "handed over" or a "team deleted" message
|
// wait for the "handed over" or a "team deleted" message
|
||||||
bool terminate = false;
|
bool terminate = false;
|
||||||
do {
|
do {
|
||||||
@@ -885,7 +904,7 @@ TeamDebugHandler::_HandlerThread()
|
|||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
debug_printf("TeamDebugHandler::_HandlerThread(): Failed to "
|
debug_printf("TeamDebugHandler::_HandlerThread(): Failed to "
|
||||||
"pop message: %s", strerror(error));
|
"pop message: %s", strerror(error));
|
||||||
kill = true;
|
debugAction = kActionKillTeam;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -907,7 +926,7 @@ TeamDebugHandler::_HandlerThread()
|
|||||||
debug_printf("debug_server: The debugger for team %"
|
debug_printf("debug_server: The debugger for team %"
|
||||||
B_PRId32 " seems to be gone.", fTeam);
|
B_PRId32 " seems to be gone.", fTeam);
|
||||||
|
|
||||||
kill = true;
|
debugAction = kActionKillTeam;
|
||||||
terminate = true;
|
terminate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -915,9 +934,9 @@ TeamDebugHandler::_HandlerThread()
|
|||||||
delete message;
|
delete message;
|
||||||
} while (!terminate);
|
} while (!terminate);
|
||||||
} else
|
} else
|
||||||
kill = true;
|
debugAction = kActionKillTeam;
|
||||||
|
|
||||||
if (kill) {
|
if (debugAction == kActionKillTeam) {
|
||||||
// kill the team
|
// kill the team
|
||||||
_KillTeam();
|
_KillTeam();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user