hrev44881 adds 3 changesets to branch 'master' old head: ae10992d0e6ba489e561e39b374fe3462eff4678 new head: 4e156d9a789fe4d0ab203c6e563abf4d9ec16299 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=4e156d9+%5Eae10992 ---------------------------------------------------------------------------- 137bb1e: Extend CLI debug report command to optionally accept a report path. 6799de3: Add command line option to ask Debugger to save a report. - When invoked, starts up the CLI such that it bypasses waiting for input and instead save a crash report of the running team, then exits. Mainly intended to be used by debug_server. 4e156d9: 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. [ Rene Gollent <anevilyak@xxxxxxxxx> ] ---------------------------------------------------------------------------- 5 files changed, 98 insertions(+), 35 deletions(-) src/apps/debugger/Debugger.cpp | 28 +++++++-- .../user_interface/cli/CliDebugReportCommand.cpp | 21 +++++-- .../cli/CommandLineUserInterface.cpp | 18 +++++- .../cli/CommandLineUserInterface.h | 5 +- src/servers/debug/DebugServer.cpp | 61 +++++++++++++------- ############################################################################ Commit: 137bb1e2aa9b1857614e10300af39c041cf6f047 URL: http://cgit.haiku-os.org/haiku/commit/?id=137bb1e Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Fri Nov 23 17:45:40 2012 UTC Extend CLI debug report command to optionally accept a report path. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/user_interface/cli/CliDebugReportCommand.cpp b/src/apps/debugger/user_interface/cli/CliDebugReportCommand.cpp index 213b5f7..62155a8 100644 --- a/src/apps/debugger/user_interface/cli/CliDebugReportCommand.cpp +++ b/src/apps/debugger/user_interface/cli/CliDebugReportCommand.cpp @@ -28,12 +28,23 @@ CliDebugReportCommand::CliDebugReportCommand() void CliDebugReportCommand::Execute(int argc, const char* const* argv, CliContext& context) { - char buffer[B_FILE_NAME_LENGTH]; - UiUtils::ReportNameForTeam(context.GetTeam(), buffer, sizeof(buffer)); BPath path; - find_directory(B_DESKTOP_DIRECTORY, &path); - path.Append(buffer); + if (argc > 1) { + path.SetTo(argv[1]); + if (path.InitCheck() != B_OK) { + printf("Invalid report path %s given.\n", argv[1]); + return; + } + } else { + char buffer[B_FILE_NAME_LENGTH]; + UiUtils::ReportNameForTeam(context.GetTeam(), buffer, sizeof(buffer)); + find_directory(B_DESKTOP_DIRECTORY, &path); + path.Append(buffer); + } + entry_ref ref; - if (get_ref_for_path(path.Path(), &ref) == B_OK) + if (get_ref_for_path(path.Path(), &ref) == B_OK) { + printf("Saving debug information report to %s...\n", path.Path()); context.GetUserInterfaceListener()->DebugReportRequested(&ref); + } } ############################################################################ Commit: 6799de315e5b0bbd65d73435ac886315bcf706b3 URL: http://cgit.haiku-os.org/haiku/commit/?id=6799de3 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Fri Nov 23 17:46:29 2012 UTC Add command line option to ask Debugger to save a report. - When invoked, starts up the CLI such that it bypasses waiting for input and instead save a crash report of the running team, then exits. Mainly intended to be used by debug_server. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/Debugger.cpp b/src/apps/debugger/Debugger.cpp index 9a25be1..295b054 100644 --- a/src/apps/debugger/Debugger.cpp +++ b/src/apps/debugger/Debugger.cpp @@ -56,8 +56,10 @@ static const char* kUsage = "fourth form additionally stops the specified thread.\n" "\n" "Options:\n" - " -h, --help - Print this usage info and exit.\n" - " -c, --cli - Use command line user interface\n" + " -h, --help - Print this usage info and exit.\n" + " -c, --cli - Use command line user interface\n" + " -s, --save-report - Save crash report for the targetted team and exit.\n" + " Implies --cli.\n" ; @@ -76,6 +78,8 @@ struct Options { team_id team; thread_id thread; bool useCLI; + bool saveReport; + const char* reportPath; Options() : @@ -83,7 +87,9 @@ struct Options { commandLineArgv(NULL), team(-1), thread(-1), - useCLI(false) + useCLI(false), + saveReport(false), + reportPath(NULL) { } }; @@ -105,15 +111,16 @@ parse_arguments(int argc, const char* const* argv, bool noOutput, while (true) { static struct option sLongOptions[] = { { "help", no_argument, 0, 'h' }, + { "cli", no_argument, 0, 'c' }, + { "save-report", optional_argument, 0, 's' }, { "team", required_argument, 0, 't' }, { "thread", required_argument, 0, 'T' }, - { "cli", no_argument, 0, 'c' }, { 0, 0, 0, 0 } }; opterr = 0; // don't print errors - int c = getopt_long(argc, (char**)argv, "+ch", sLongOptions, NULL); + int c = getopt_long(argc, (char**)argv, "+chs", sLongOptions, NULL); if (c == -1) break; @@ -128,6 +135,14 @@ parse_arguments(int argc, const char* const* argv, bool noOutput, print_usage_and_exit(false); break; + case 's': + { + options.useCLI = true; + options.saveReport = true; + options.reportPath = optarg; + break; + } + case 't': { options.team = strtol(optarg, NULL, 0); @@ -581,7 +596,8 @@ CliDebugger::Run(const Options& options) // create the command line UI CommandLineUserInterface* userInterface - = new(std::nothrow) CommandLineUserInterface; + = new(std::nothrow) CommandLineUserInterface(options.saveReport, + options.reportPath); if (userInterface == NULL) { fprintf(stderr, "Error: Out of memory!\n"); return false; diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp index e6d2bb0..a909727 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp @@ -88,9 +88,12 @@ private: // #pragma mark - CommandLineUserInterface -CommandLineUserInterface::CommandLineUserInterface() +CommandLineUserInterface::CommandLineUserInterface(bool saveReport, + const char* reportPath) : fCommands(20, true), + fReportPath(reportPath), + fSaveReport(saveReport), fShowSemaphore(-1), fShown(false), fTerminating(false) @@ -202,7 +205,18 @@ CommandLineUserInterface::Run() if (error != B_OK) return; - _InputLoop(); + if (!fSaveReport) + _InputLoop(); + else { + ArgumentVector args; + char buffer[256]; + const char* parseErrorLocation; + snprintf(buffer, sizeof(buffer), "save-report %s", + fReportPath != NULL ? fReportPath : ""); + args.Parse(buffer, &parseErrorLocation); + _ExecuteCommand(args.ArgumentCount(), args.Arguments()); + fContext.QuitSession(true); + } // Release the Show() semaphore to signal Terminate(). release_sem(fShowSemaphore); diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h index 6bede60..fc01510 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h @@ -19,7 +19,8 @@ class CliCommand; class CommandLineUserInterface : public UserInterface { public: - CommandLineUserInterface(); + CommandLineUserInterface(bool saveReport, + const char* reportPath); virtual ~CommandLineUserInterface(); virtual const char* ID() const; @@ -70,6 +71,8 @@ private: private: CliContext fContext; CommandList fCommands; + const char* fReportPath; + bool fSaveReport; sem_id fShowSemaphore; bool fShown; volatile bool fTerminating; ############################################################################ Revision: hrev44881 Commit: 4e156d9a789fe4d0ab203c6e563abf4d9ec16299 URL: http://cgit.haiku-os.org/haiku/commit/?id=4e156d9 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Fri Nov 23 18:23:24 2012 UTC 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. ---------------------------------------------------------------------------- diff --git a/src/servers/debug/DebugServer.cpp b/src/servers/debug/DebugServer.cpp index fe795b5..3fa4b73 100644 --- a/src/servers/debug/DebugServer.cpp +++ b/src/servers/debug/DebugServer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011, Rene Gollent, rene@xxxxxxxxxxxx + * Copyright 2011-2012, Rene Gollent, rene@xxxxxxxxxxxx * Copyright 2005-2009, Ingo Weinhold, bonefish@xxxxxxxxxxxxx * Distributed under the terms of the MIT License. */ @@ -34,6 +34,13 @@ #include <util/DoublyLinkedList.h> +enum { + kActionKillTeam, + kActionDebugTeam, + kActionSaveReportTeam +}; + + #define HANDOVER_USE_GDB 1 //#define HANDOVER_USE_DEBUGGER 1 @@ -118,11 +125,11 @@ public: private: status_t _PopMessage(DebugMessage *&message); - thread_id _EnterDebugger(); + thread_id _EnterDebugger(bool saveReport); status_t _SetupGDBArguments(BStringList &arguments, bool usingConsoled); void _KillTeam(); - bool _HandleMessage(DebugMessage *message); + int32 _HandleMessage(DebugMessage *message); void _LookupSymbolAddress(debug_symbol_lookup_context *lookupContext, const void *address, char *buffer, int32 bufferSize); @@ -512,7 +519,7 @@ TeamDebugHandler::_SetupGDBArguments(BStringList &arguments, bool usingConsoled) thread_id -TeamDebugHandler::_EnterDebugger() +TeamDebugHandler::_EnterDebugger(bool saveReport) { TRACE(("debug_server: TeamDebugHandler::_EnterDebugger(): team %" B_PRId32 "\n", fTeam)); @@ -575,6 +582,10 @@ TeamDebugHandler::_EnterDebugger() BString debuggerParam; debuggerParam.SetToFormat("%" B_PRId32, fTeam); + if (saveReport) { + if (!arguments.Add("--save-report")) + return B_NO_MEMORY; + } if (!arguments.Add("--team") || !arguments.Add(debuggerParam)) return B_NO_MEMORY; @@ -610,7 +621,7 @@ TeamDebugHandler::_KillTeam() } -bool +int32 TeamDebugHandler::_HandleMessage(DebugMessage *message) { // This method is called only for the first message the debugger gets for @@ -669,12 +680,12 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message) _PrintStackTrace(thread); - bool kill = true; + int32 debugAction = kActionKillTeam; // ask the user whether to debug or kill the team if (_IsGUIServer()) { // App server, input server, or registrar. We always debug those. - kill = false; + debugAction = kActionDebugTeam; } else if (USE_GUI && _AreGUIServersAlive() && _InitGUI() == B_OK) { // normal app -- tell the user _NotifyAppServer(fTeam); @@ -688,16 +699,24 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message) // TODO: It would be nice if the alert would go away automatically // if someone else kills our teams. +#ifdef HANDOVER_USE_DEBUGGER 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); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); - int32 result = alert->Go(); - kill = (result == 1); - _NotifyRegistrar(fTeam, false, !kill); + debugAction = alert->Go(); + _NotifyRegistrar(fTeam, false, debugAction != kActionKillTeam); +#endif } - return kill; + return debugAction; } @@ -858,26 +877,26 @@ TeamDebugHandler::_HandlerThread() DebugMessage *message; status_t error = _PopMessage(message); - bool kill; + int32 debugAction = kActionKillTeam; if (error == B_OK) { // handle the message - kill = _HandleMessage(message); + debugAction = _HandleMessage(message); delete message; } else { debug_printf("TeamDebugHandler::_HandlerThread(): Failed to pop " "initial message: %s", strerror(error)); - kill = true; } bool isGuiServer = _IsGUIServer(); // kill the team or hand it over to the debugger thread_id debuggerThread = -1; - if (kill) { + if (debugAction == kActionKillTeam) { // 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 // nothing here. - } else if ((debuggerThread = _EnterDebugger()) >= 0) { + } else if ((debuggerThread = _EnterDebugger( + debugAction == kActionSaveReportTeam)) >= 0) { // wait for the "handed over" or a "team deleted" message bool terminate = false; do { @@ -885,7 +904,7 @@ TeamDebugHandler::_HandlerThread() if (error != B_OK) { debug_printf("TeamDebugHandler::_HandlerThread(): Failed to " "pop message: %s", strerror(error)); - kill = true; + debugAction = kActionKillTeam; break; } @@ -907,7 +926,7 @@ TeamDebugHandler::_HandlerThread() debug_printf("debug_server: The debugger for team %" B_PRId32 " seems to be gone.", fTeam); - kill = true; + debugAction = kActionKillTeam; terminate = true; } } @@ -915,9 +934,9 @@ TeamDebugHandler::_HandlerThread() delete message; } while (!terminate); } else - kill = true; + debugAction = kActionKillTeam; - if (kill) { + if (debugAction == kActionKillTeam) { // kill the team _KillTeam(); }