コード例 #1
0
ファイル: DebugServer.cpp プロジェクト: looncraz/haiku
int32
TeamDebugHandler::_HandleMessage(DebugMessage *message)
{
	// This method is called only for the first message the debugger gets for
	// a team. That means only a few messages are actually possible, while
	// others wouldn't trigger the debugger in the first place. So we deal with
	// all of them the same way, by popping up an alert.
	TRACE(("debug_server: TeamDebugHandler::_HandleMessage(): team %" B_PRId32
		", code: %" B_PRId32 "\n", fTeam, (int32)message->Code()));

	thread_id thread = message->Data().origin.thread;

	// get some user-readable message
	char buffer[512];
	switch (message->Code()) {
		case B_DEBUGGER_MESSAGE_TEAM_DELETED:
			// This shouldn't happen.
			debug_printf("debug_server: Got a spurious "
				"B_DEBUGGER_MESSAGE_TEAM_DELETED message for team %" B_PRId32
				"\n", fTeam);
			return true;

		case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
			get_debug_exception_string(
				message->Data().exception_occurred.exception, buffer,
				sizeof(buffer));
			break;

		case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
		{
			// get the debugger() message
			void *messageAddress = message->Data().debugger_call.message;
			char messageBuffer[128];
			status_t error = B_OK;
			ssize_t bytesRead = debug_read_string(&fDebugContext,
				messageAddress, messageBuffer, sizeof(messageBuffer));
			if (bytesRead < 0)
				error = bytesRead;

			if (error == B_OK) {
				sprintf(buffer, "Debugger call: `%s'", messageBuffer);
			} else {
				snprintf(buffer, sizeof(buffer), "Debugger call: %p "
					"(Failed to read message: %s)", messageAddress,
					strerror(error));
			}
			break;
		}

		default:
			get_debug_message_string(message->Code(), buffer, sizeof(buffer));
			break;
	}

	debug_printf("debug_server: Thread %" B_PRId32 " entered the debugger: %s\n",
		thread, buffer);

	_PrintStackTrace(thread);

	int32 debugAction = kActionPromptUser;
	bool explicitActionFound = false;
	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.
		// 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);

		BString buffer(
			B_TRANSLATE("The application:\n\n      %app\n\n"
			"has encountered an error which prevents it from continuing. Haiku "
			"will terminate the application and clean up."));
		buffer.ReplaceFirst("%app", fTeamInfo.args);

		// TODO: It would be nice if the alert would go away automatically
		// if someone else kills our teams.
		BAlert *alert = new BAlert(NULL, buffer.String(),
			B_TRANSLATE("Terminate"), B_TRANSLATE("Debug"),
			B_TRANSLATE("Write core file"),
			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
#ifdef HANDOVER_USE_DEBUGGER
		alert->AddButton(B_TRANSLATE("Save report"));
#endif
		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
		debugAction = alert->Go();
		if (debugAction < 0) {
			// Happens when closed by escape key
			debugAction = kActionKillTeam;
		}
		_NotifyRegistrar(fTeam, false, debugAction != kActionKillTeam);
	}

	return debugAction;
}