debug_server: Add default action support.

- 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.
This commit is contained in:
Rene Gollent
2013-12-16 19:23:47 -05:00
parent a99cee63cc
commit 1b744548e0
2 changed files with 109 additions and 5 deletions
+107 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2012, Rene Gollent, [email protected].
* Copyright 2011-2013, Rene Gollent, [email protected].
* Copyright 2005-2009, Ingo Weinhold, [email protected].
* 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);
+2
View File
@@ -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
;