rem: if (!handOver)
add: if (releaseDebugInfoLock)
context: install_team_debugger(team_id teamID, port_id debuggerPort, bool useDefault,	bool dontFail){	TRACE(("install_team_debugger(team: %ld, port: %ld, default: %d, "		"dontFail: %d)\n", teamID, debuggerPort, useDefault, dontFail));	if (useDefault)		debuggerPort = atomic_get(&sDefaultDebuggerPort);	// get the debugger team	port_info debuggerPortInfo;	status_t error = get_port_info(debuggerPort, &debuggerPortInfo);	if (error != B_OK) {		TRACE(("install_team_debugger(): Failed to get debugger port info: "			"%lx\n", error));		return error;	}	team_id debuggerTeam = debuggerPortInfo.team;	// check the debugger team: It must neither be the kernel team nor the	// debugged team	if (debuggerTeam == team_get_kernel_team_id() || debuggerTeam == teamID) {		TRACE(("install_team_debugger(): Can't debug kernel or debugger team. "			"debugger: %ld, debugged: %ld\n", debuggerTeam, teamID));		return B_NOT_ALLOWED;	}	// check, if a debugger is already installed	bool done = false;	port_id result = B_ERROR;	bool handOver = false;	port_id oldDebuggerPort = -1;	port_id nubPort = -1;	cpu_status state = disable_interrupts();	GRAB_TEAM_LOCK();	// get a real team ID	// We look up the team by ID, even in case of the current team, so we can be	// sure, that the team is not already dying.	if (teamID == B_CURRENT_TEAM)		teamID = thread_get_current_thread()->team->id;	struct team *team = team_get_team_struct_locked(teamID);	if (team) {		GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);		int32 teamDebugFlags = team->debug_info.flags;		if (team == team_get_kernel_team()) {			// don't allow to debug the kernel			error = B_NOT_ALLOWED;		} else if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {			if (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_HANDOVER) {				// a handover to another debugger is requested				// clear the flag				atomic_and(& team->debug_info.flags,					~B_TEAM_DEBUG_DEBUGGER_HANDOVER);				oldDebuggerPort = team->debug_info.debugger_port;				result = nubPort = team->debug_info.nub_port;				// set the new debugger				install_team_debugger_init_debug_infos(team, debuggerTeam,					debuggerPort, nubPort, team->debug_info.nub_thread,					team->debug_info.debugger_write_lock);				handOver = true;				done = true;			} else {				// there's already a debugger installed				error = (dontFail ? B_OK : B_BAD_VALUE);				done = true;				result = team->debug_info.nub_port;			}		}		// in case of a handover the lock is already released		if (!handOver)			RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);	} else		error = B_BAD_TEAM_ID;	RELEASE_TEAM_LOCK();	restore_interrupts(state);	if (handOver) {		// notify the nub thread		kill_interruptable_write_port(nubPort, B_DEBUG_MESSAGE_HANDED_OVER,			NULL, 0);		// notify the old debugger		debug_handed_over notification;		notification.origin.thread = -1;		notification.origin.team = teamID;		notification.origin.nub_port = nubPort;		notification.debugger = debuggerTeam;		notification.debugger_port = debuggerPort;		error = write_port_etc(oldDebuggerPort,			B_DEBUGGER_MESSAGE_HANDED_OVER, &notification,			sizeof(notification), B_RELATIVE_TIMEOUT, 0);		if (error != B_OK) {			TRACE(("install_team_debugger(): Failed to send message to old "				"debugger: %s\n", strerror(error)));		}		TRACE(("install_team_debugger() done: handed over to debugger: team: "			"%ld, port: %ld\n", debuggerTeam, debuggerPort));		return result;	}	if (done || error != B_OK) {		TRACE(("install_team_debugger() done1: %ld\n",			(error == B_OK ? result : error)));		return (error == B_OK ? result : error);	}	// create the debugger write lock semaphore	char nameBuffer[B_OS_NAME_LENGTH];	snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debugger port write",		teamID);	sem_id debuggerWriteLock = create_sem(1, nameBuffer);	if (debuggerWriteLock < 0)		error = debuggerWriteLock;	// create the nub port	snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debug", teamID);	if (error == B_OK) {		nubPort = create_port(1, nameBuffer);		if (nubPort < 0)			error = nubPort;		else			result = nubPort;	}	// make the debugger team the port owner; thus we know, if the debugger is	// gone and can cleanup	if (error == B_OK)		error = set_port_owner(nubPort, debuggerTeam);	// spawn the nub thread	thread_id nubThread = -1;	if (error == B_OK) {		snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debug task", teamID);		nubThread = spawn_kernel_thread_etc(debug_nub_thread, nameBuffer,			B_NORMAL_PRIORITY, NULL, teamID, -1);		if (nubThread < 0)			error = nubThread;	}	// now adjust the debug info accordingly	if (error == B_OK) {		state = disable_interrupts();		GRAB_TEAM_LOCK();		// look up again, to make sure the team isn't dying		team = team_get_team_struct_locked(teamID);		if (team) {			GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);			if (team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) {				// there's already a debugger installed				error = (dontFail ? B_OK : B_BAD_VALUE);				done = true;				result = team->debug_info.nub_port;				RELEASE_TEAM_DEBUG_INFO_LOCK(team->debug_info);			} else {				install_team_debugger_init_debug_infos(team, debuggerTeam,					debuggerPort, nubPort, nubThread, debuggerWriteLock);			}		} else			error = B_BAD_TEAM_ID;		RELEASE_TEAM_LOCK();		restore_interrupts(state);	}	// if everything went fine, resume the nub thread, otherwise clean up	if (error == B_OK && !done) {		resume_thread(nubThread);	} else {		// delete port and terminate thread		if (nubPort >= 0) {			set_port_owner(nubPort, B_CURRENT_TEAM);			delete_port(nubPort);		}		if (nubThread >= 0) {			int32 result;			wait_for_thread(nubThread, &result);		}	}	TRACE(("install_team_debugger() done2: %ld\n",		(error == B_OK ? result : error)));	return (error == B_OK ? result : error);}