summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRene Gollent <rene@gollent.com>2013-12-15 15:57:23 (GMT)
committerRene Gollent <rene@gollent.com>2013-12-17 00:23:47 (GMT)
commit1b744548e0a31d725a147cfeadf3eeb30a4eb84c (patch)
treefd7a803c5b8e15ba89fe7d746277ccf3271dbb9b
parenta99cee63cccfe4d8fbdbdd8f565c466ba3edacea (diff)
debug_server: Add default action support.hrev46547
- debug_server now supports user configuration of both the general default action to be taken on crashes, and per-app overrides. These are stored config/settings/system/debug_server/settings. In the absence of the file, behavior defaults to prompting the user for an action as before. The file takes on a driver_settings style format as follows: --- default_action user executable_actions { app1 log /path/app2* debug } --- Valid values for an action are: - user = prompt user for action. - kill = silently terminate the crashing team. - debug = attach the debugger to the crashing team. in the debugger. - log / report = save a crash report and terminate the team. If no default_action is specified, "user" is assumed. The executable_actions subsection contains individual overrides of the default. These take the form above, where the individual lines can be only a team name, or a path, with wildcards. Implements first part of #10301.
-rw-r--r--src/servers/debug/DebugServer.cpp112
-rw-r--r--src/servers/debug/Jamfile2
2 files changed, 109 insertions, 5 deletions
diff --git a/src/servers/debug/DebugServer.cpp b/src/servers/debug/DebugServer.cpp
index 9a8ec74..8386ba3 100644
--- a/src/servers/debug/DebugServer.cpp
+++ b/src/servers/debug/DebugServer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2012, Rene Gollent, rene@gollent.com.
+ * Copyright 2011-2013, Rene Gollent, rene@gollent.com.
* Copyright 2005-2009, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
@@ -25,7 +25,9 @@
#include <Locale.h>
#include <Path.h>
+#include <DriverSettings.h>
#include <MessengerPrivate.h>
+#include <RegExp.h>
#include <RegistrarDefs.h>
#include <RosterPrivate.h>
#include <Server.h>
@@ -37,7 +39,8 @@
enum {
kActionKillTeam,
kActionDebugTeam,
- kActionSaveReportTeam
+ kActionSaveReportTeam,
+ kActionPromptUser
};
@@ -65,6 +68,95 @@ using std::nothrow;
static const char *kSignature = "application/x-vnd.Haiku-debug_server";
+static status_t
+action_for_string(const char* action, int32& _action)
+{
+ if (strcmp(action, "kill") == 0)
+ _action = kActionKillTeam;
+ else if (strcmp(action, "debug") == 0)
+ _action = kActionDebugTeam;
+ else if (strcmp(action, "log") == 0
+ || strcmp(action, "report") == 0) {
+ _action = kActionSaveReportTeam;
+ }
+ else if (strcasecmp(action, "user") == 0)
+ _action = kActionPromptUser;
+ else
+ return B_BAD_VALUE;
+
+ return B_OK;
+}
+
+
+static bool
+match_team_name(const char* teamName, const char* parameterName)
+{
+ RegExp expressionMatcher;
+ if (expressionMatcher.SetPattern(parameterName,
+ RegExp::PATTERN_TYPE_WILDCARD)) {
+ BString value = teamName;
+ if (parameterName[0] != '/') {
+ // the expression in question is a team name match only,
+ // so we need to extract that.
+ BPath path(teamName);
+ if (path.InitCheck() == B_OK)
+ value = path.Leaf();
+ }
+
+ RegExp::MatchResult match = expressionMatcher.Match(value);
+ if (match.HasMatched())
+ return true;
+ }
+
+ return false;
+}
+
+
+static
+status_t action_for_team(const char* teamName, int32& _action,
+ bool& _explicitActionFound)
+{
+ status_t error = B_OK;
+ BPath path;
+ error = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
+ if (error != B_OK)
+ return error;
+
+ path.Append("system/debug_server/settings");
+ BDriverSettings settings;
+ error = settings.Load(path.Path());
+ if (error != B_OK)
+ return error;
+
+ int32 tempAction;
+ if (action_for_string(settings.GetParameterValue("default_action",
+ "user", "user"), tempAction) == B_OK) {
+ _action = tempAction;
+ } else
+ _action = kActionPromptUser;
+ _explicitActionFound = false;
+
+ BDriverParameter parameter = settings.GetParameter("executable_actions");
+ for (BDriverParameterIterator iterator = parameter.ParameterIterator();
+ iterator.HasNext();) {
+ BDriverParameter child = iterator.Next();
+ if (!match_team_name(teamName, child.Name()))
+ continue;
+
+ if (child.CountValues() > 0) {
+ if (action_for_string(child.ValueAt(0), tempAction) == B_OK) {
+ _action = tempAction;
+ _explicitActionFound = true;
+ }
+ }
+
+ break;
+ }
+
+ return B_OK;
+}
+
+
static void
KillTeam(team_id team, const char *appName = NULL)
{
@@ -275,6 +367,7 @@ private:
TeamDebugHandlerMap fHandlers;
};
+
TeamDebugHandlerRoster *TeamDebugHandlerRoster::sRoster = NULL;
@@ -693,13 +786,22 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message)
_PrintStackTrace(thread);
- int32 debugAction = kActionKillTeam;
+ int32 debugAction;
+ bool explicitActionFound;
+ if (action_for_team(fExecutablePath, debugAction, explicitActionFound)
+ != B_OK) {
+ debugAction = kActionPromptUser;
+ explicitActionFound = false;
+ }
// ask the user whether to debug or kill the team
if (_IsGUIServer()) {
// App server, input server, or registrar. We always debug those.
- debugAction = kActionDebugTeam;
- } else if (USE_GUI && _AreGUIServersAlive() && _InitGUI() == B_OK) {
+ // if not specifically overridden.
+ if (!explicitActionFound)
+ debugAction = kActionDebugTeam;
+ } else if (debugAction == kActionPromptUser && USE_GUI
+ && _AreGUIServersAlive() && _InitGUI() == B_OK) {
// normal app -- tell the user
_NotifyAppServer(fTeam);
_NotifyRegistrar(fTeam, true, false);
diff --git a/src/servers/debug/Jamfile b/src/servers/debug/Jamfile
index e9a07d4..947af46 100644
--- a/src/servers/debug/Jamfile
+++ b/src/servers/debug/Jamfile
@@ -4,6 +4,7 @@ UsePrivateHeaders app ;
UsePrivateHeaders debug ;
UsePrivateHeaders kernel ;
UsePrivateHeaders shared ;
+UsePrivateHeaders storage ;
AddResources debug_server : debug_server.rdef ;
@@ -13,6 +14,7 @@ Server debug_server
:
be
libdebug.so
+ libshared.a
$(TARGET_LIBSTDC++)
localestub
;