From 7db4a655b56b2a99f9c5be7d4780a9a336c366e7 Mon Sep 17 00:00:00 2001
From: Rene Gollent <rene@gollent.com>
Date: Sun, 15 Dec 2013 10:57:23 -0500
Subject: [PATCH] debug_server: Add default action support.
- TeamDebugHandlerRoster now stores both a global default action to be taken
when a team crashes, as well as one or more pattern matches to override said
default for particular teams. These mappings are looked for in the settings
file system/debug_server/settings. In the absence of the file, behavior
defaults to prompting the user for an action as before. The file's format is
driver_settings style, and follows the parameter names specified in ticket
10301.
---
src/servers/debug/DebugServer.cpp | 122 +++++++++++++++++++++++++++++++++++---
src/servers/debug/Jamfile | 1 +
2 files changed, 116 insertions(+), 7 deletions(-)
diff --git a/src/servers/debug/DebugServer.cpp b/src/servers/debug/DebugServer.cpp
index 9a8ec74..68fa185 100644
a
|
b
|
|
1 | 1 | /* |
2 | | * Copyright 2011-2012, Rene Gollent, rene@gollent.com. |
| 2 | * Copyright 2011-2013, Rene Gollent, rene@gollent.com. |
3 | 3 | * Copyright 2005-2009, Ingo Weinhold, bonefish@users.sf.net. |
4 | 4 | * Distributed under the terms of the MIT License. |
5 | 5 | */ |
… |
… |
|
19 | 19 | #include <Autolock.h> |
20 | 20 | #include <Catalog.h> |
21 | 21 | #include <debug_support.h> |
| 22 | #include <driver_settings.h> |
22 | 23 | #include <Entry.h> |
23 | 24 | #include <FindDirectory.h> |
24 | 25 | #include <Invoker.h> |
… |
… |
|
26 | 27 | #include <Path.h> |
27 | 28 | |
28 | 29 | #include <MessengerPrivate.h> |
| 30 | #include <RegExp.h> |
29 | 31 | #include <RegistrarDefs.h> |
30 | 32 | #include <RosterPrivate.h> |
31 | 33 | #include <Server.h> |
… |
… |
|
37 | 39 | enum { |
38 | 40 | kActionKillTeam, |
39 | 41 | kActionDebugTeam, |
40 | | kActionSaveReportTeam |
| 42 | kActionSaveReportTeam, |
| 43 | kActionPromptUser |
41 | 44 | }; |
42 | 45 | |
43 | 46 | |
… |
… |
using std::nothrow;
|
65 | 68 | static const char *kSignature = "application/x-vnd.Haiku-debug_server"; |
66 | 69 | |
67 | 70 | |
| 71 | static int32 action_for_string(const char* action, int32 defaultAction) |
| 72 | { |
| 73 | if (strcasecmp(action, "kill") == 0) |
| 74 | return kActionKillTeam; |
| 75 | else if (strcasecmp(action, "debug") == 0) |
| 76 | return kActionDebugTeam; |
| 77 | else if (strcasecmp(action, "log") == 0) |
| 78 | return kActionSaveReportTeam; |
| 79 | else if (strcasecmp(action, "user") == 0) |
| 80 | return kActionPromptUser; |
| 81 | |
| 82 | return defaultAction; |
| 83 | } |
| 84 | |
| 85 | |
68 | 86 | static void |
69 | 87 | KillTeam(team_id team, const char *appName = NULL) |
70 | 88 | { |
… |
… |
class TeamDebugHandlerRoster : public BLocker {
|
167 | 185 | private: |
168 | 186 | TeamDebugHandlerRoster() |
169 | 187 | : |
170 | | BLocker("team debug handler roster") |
| 188 | BLocker("team debug handler roster"), |
| 189 | fDefaultDebugAction(kActionPromptUser) |
171 | 190 | { |
172 | 191 | } |
173 | 192 | |
… |
… |
public:
|
185 | 204 | return sRoster; |
186 | 205 | } |
187 | 206 | |
| 207 | status_t Init() |
| 208 | { |
| 209 | status_t error = B_OK; |
| 210 | BPath path; |
| 211 | error = find_directory(B_USER_SETTINGS_DIRECTORY, &path); |
| 212 | if (error != B_OK) |
| 213 | return error; |
| 214 | |
| 215 | path.Append("system/debug_server/settings"); |
| 216 | void* handle = load_driver_settings(path.Path()); |
| 217 | if (handle) { |
| 218 | const driver_settings* settings = get_driver_settings(handle); |
| 219 | for (int i = 0; i < settings->parameter_count; i++) { |
| 220 | const driver_parameter& parameter = settings->parameters[i]; |
| 221 | if (strcasecmp(parameter.name, "default_action") == 0 |
| 222 | && parameter.value_count > 0) { |
| 223 | fDefaultDebugAction = action_for_string( |
| 224 | parameter.values[0], fDefaultDebugAction); |
| 225 | } else if (strcasecmp(parameter.name, "executable_actions") |
| 226 | == 0) { |
| 227 | for (int j = 0; j < parameter.parameter_count; j++) { |
| 228 | const driver_parameter &execParameter |
| 229 | = parameter.parameters[j]; |
| 230 | if (execParameter.value_count > 0) { |
| 231 | fDefaultActions[execParameter.name] |
| 232 | = action_for_string(execParameter.values[0], |
| 233 | fDefaultDebugAction); |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | unload_driver_settings(handle); |
| 240 | } |
| 241 | |
| 242 | return B_OK; |
| 243 | } |
| 244 | |
188 | 245 | bool AddHandler(TeamDebugHandler *handler) |
189 | 246 | { |
190 | 247 | if (!handler) |
… |
… |
public:
|
225 | 282 | return handler; |
226 | 283 | } |
227 | 284 | |
| 285 | int32 DefaultActionForTeam(const BString& teamName, bool& _matchFound) const |
| 286 | { |
| 287 | _matchFound = false; |
| 288 | RegExp expressionMatcher; |
| 289 | for (DefaultActionMap::const_iterator it = fDefaultActions.begin(); |
| 290 | it != fDefaultActions.end(); ++it) { |
| 291 | if (expressionMatcher.SetPattern(it->first, |
| 292 | RegExp::PATTERN_TYPE_WILDCARD)) { |
| 293 | BString value = teamName; |
| 294 | if (it->first[0] != '/') { |
| 295 | // the expression in question is a team name match only, |
| 296 | // so we need to extract that. |
| 297 | BPath path(teamName); |
| 298 | if (path.InitCheck() == B_OK) |
| 299 | value = path.Leaf(); |
| 300 | } |
| 301 | RegExp::MatchResult match = expressionMatcher.Match(value); |
| 302 | if (match.HasMatched()) { |
| 303 | _matchFound = true; |
| 304 | return it->second; |
| 305 | } |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | return fDefaultDebugAction; |
| 310 | } |
| 311 | |
228 | 312 | status_t DispatchMessage(DebugMessage *message) |
229 | 313 | { |
230 | 314 | if (!message) |
… |
… |
public:
|
269 | 353 | |
270 | 354 | private: |
271 | 355 | typedef map<team_id, TeamDebugHandler*> TeamDebugHandlerMap; |
| 356 | typedef map<BString, int32> DefaultActionMap; |
272 | 357 | |
273 | 358 | static TeamDebugHandlerRoster *sRoster; |
274 | 359 | |
275 | 360 | TeamDebugHandlerMap fHandlers; |
| 361 | |
| 362 | int32 fDefaultDebugAction; |
| 363 | // this indicates the default action |
| 364 | // to take on crash in the absence of |
| 365 | // a more specific match in the map. |
| 366 | DefaultActionMap fDefaultActions; |
| 367 | // contains a set of string->action |
| 368 | // mappings for team names. Can contain |
| 369 | // wild cards. |
| 370 | |
276 | 371 | }; |
277 | 372 | |
278 | 373 | TeamDebugHandlerRoster *TeamDebugHandlerRoster::sRoster = NULL; |
… |
… |
TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
693 | 788 | |
694 | 789 | _PrintStackTrace(thread); |
695 | 790 | |
696 | | int32 debugAction = kActionKillTeam; |
| 791 | bool explicitActionFound = false; |
| 792 | int32 debugAction = TeamDebugHandlerRoster::Default() |
| 793 | ->DefaultActionForTeam(fExecutablePath, explicitActionFound); |
697 | 794 | |
698 | 795 | // ask the user whether to debug or kill the team |
699 | 796 | if (_IsGUIServer()) { |
700 | 797 | // App server, input server, or registrar. We always debug those. |
701 | | debugAction = kActionDebugTeam; |
702 | | } else if (USE_GUI && _AreGUIServersAlive() && _InitGUI() == B_OK) { |
| 798 | // if not specifically overridden. |
| 799 | if (!explicitActionFound) |
| 800 | debugAction = kActionDebugTeam; |
| 801 | } else if (debugAction == kActionPromptUser && USE_GUI |
| 802 | && _AreGUIServersAlive() && _InitGUI() == B_OK) { |
703 | 803 | // normal app -- tell the user |
704 | 804 | _NotifyAppServer(fTeam); |
705 | 805 | _NotifyRegistrar(fTeam, true, false); |
… |
… |
main()
|
1154 | 1254 | close(console); |
1155 | 1255 | |
1156 | 1256 | // create the team debug handler roster |
1157 | | if (!TeamDebugHandlerRoster::CreateDefault()) { |
| 1257 | TeamDebugHandlerRoster* roster = TeamDebugHandlerRoster::CreateDefault(); |
| 1258 | if (!roster) { |
1158 | 1259 | debug_printf("debug_server: Failed to create team debug handler " |
1159 | 1260 | "roster.\n"); |
1160 | 1261 | exit(1); |
1161 | 1262 | } |
1162 | 1263 | |
| 1264 | // initialize roster settings |
| 1265 | if (roster->Init() != B_OK) { |
| 1266 | debug_printf("debug_server: Failed to initialize team debug handler " |
| 1267 | "roster.\n"); |
| 1268 | exit(1); |
| 1269 | } |
| 1270 | |
1163 | 1271 | // create application |
1164 | 1272 | DebugServer server(error); |
1165 | 1273 | if (error != B_OK) { |
diff --git a/src/servers/debug/Jamfile b/src/servers/debug/Jamfile
index e9a07d4..bb13d6a 100644
a
|
b
|
Server debug_server
|
13 | 13 | : |
14 | 14 | be |
15 | 15 | libdebug.so |
| 16 | libshared.a |
16 | 17 | $(TARGET_LIBSTDC++) |
17 | 18 | localestub |
18 | 19 | ; |