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:
@@ -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].
|
* Copyright 2005-2009, Ingo Weinhold, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -25,7 +25,9 @@
|
|||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
|
|
||||||
|
#include <DriverSettings.h>
|
||||||
#include <MessengerPrivate.h>
|
#include <MessengerPrivate.h>
|
||||||
|
#include <RegExp.h>
|
||||||
#include <RegistrarDefs.h>
|
#include <RegistrarDefs.h>
|
||||||
#include <RosterPrivate.h>
|
#include <RosterPrivate.h>
|
||||||
#include <Server.h>
|
#include <Server.h>
|
||||||
@@ -37,7 +39,8 @@
|
|||||||
enum {
|
enum {
|
||||||
kActionKillTeam,
|
kActionKillTeam,
|
||||||
kActionDebugTeam,
|
kActionDebugTeam,
|
||||||
kActionSaveReportTeam
|
kActionSaveReportTeam,
|
||||||
|
kActionPromptUser
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -65,6 +68,95 @@ using std::nothrow;
|
|||||||
static const char *kSignature = "application/x-vnd.Haiku-debug_server";
|
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
|
static void
|
||||||
KillTeam(team_id team, const char *appName = NULL)
|
KillTeam(team_id team, const char *appName = NULL)
|
||||||
{
|
{
|
||||||
@@ -275,6 +367,7 @@ private:
|
|||||||
TeamDebugHandlerMap fHandlers;
|
TeamDebugHandlerMap fHandlers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
TeamDebugHandlerRoster *TeamDebugHandlerRoster::sRoster = NULL;
|
TeamDebugHandlerRoster *TeamDebugHandlerRoster::sRoster = NULL;
|
||||||
|
|
||||||
|
|
||||||
@@ -693,13 +786,22 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
|||||||
|
|
||||||
_PrintStackTrace(thread);
|
_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
|
// 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.
|
||||||
debugAction = kActionDebugTeam;
|
// if not specifically overridden.
|
||||||
} else if (USE_GUI && _AreGUIServersAlive() && _InitGUI() == B_OK) {
|
if (!explicitActionFound)
|
||||||
|
debugAction = kActionDebugTeam;
|
||||||
|
} else if (debugAction == kActionPromptUser && USE_GUI
|
||||||
|
&& _AreGUIServersAlive() && _InitGUI() == B_OK) {
|
||||||
// normal app -- tell the user
|
// normal app -- tell the user
|
||||||
_NotifyAppServer(fTeam);
|
_NotifyAppServer(fTeam);
|
||||||
_NotifyRegistrar(fTeam, true, false);
|
_NotifyRegistrar(fTeam, true, false);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ UsePrivateHeaders app ;
|
|||||||
UsePrivateHeaders debug ;
|
UsePrivateHeaders debug ;
|
||||||
UsePrivateHeaders kernel ;
|
UsePrivateHeaders kernel ;
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
|
UsePrivateHeaders storage ;
|
||||||
|
|
||||||
AddResources debug_server : debug_server.rdef ;
|
AddResources debug_server : debug_server.rdef ;
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ Server debug_server
|
|||||||
:
|
:
|
||||||
be
|
be
|
||||||
libdebug.so
|
libdebug.so
|
||||||
|
libshared.a
|
||||||
$(TARGET_LIBSTDC++)
|
$(TARGET_LIBSTDC++)
|
||||||
localestub
|
localestub
|
||||||
;
|
;
|
||||||
|
|||||||
Reference in New Issue
Block a user