Enforce team and thread limits

Also fixes incorrect team accounting in case of error when creating
a team. The previously incremented sUsedTeams wasn't decremented again.
This commit is contained in:
Ingo Weinhold
2013-07-02 01:57:30 +02:00
parent cbcde3ba80
commit 2eb2b522bf
2 changed files with 42 additions and 5 deletions
+20 -2
View File
@@ -1707,7 +1707,9 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount,
InterruptsSpinLocker teamsLocker(sTeamHashLock);
sTeamHash.Insert(team);
sUsedTeams++;
bool teamLimitReached = sUsedTeams >= sMaxTeams;
if (!teamLimitReached)
sUsedTeams++;
teamsLocker.Unlock();
@@ -1727,6 +1729,11 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount,
// check the executable's set-user/group-id permission
update_set_id_user_and_group(team, path);
if (teamLimitReached) {
status = B_NO_MORE_TEAMS;
goto err1;
}
status = create_team_arg(&teamArgs, path, flatArgs, flatArgsSize, argCount,
envCount, (mode_t)-1, errorPort, errorToken);
if (status != B_OK)
@@ -1834,6 +1841,8 @@ err1:
teamsLocker.Lock();
sTeamHash.Remove(team);
if (!teamLimitReached)
sUsedTeams--;
teamsLocker.Unlock();
sNotificationService.Notify(TEAM_REMOVED, team);
@@ -2038,7 +2047,9 @@ fork_team(void)
InterruptsSpinLocker teamsLocker(sTeamHashLock);
sTeamHash.Insert(team);
sUsedTeams++;
bool teamLimitReached = sUsedTeams >= sMaxTeams;
if (!teamLimitReached)
sUsedTeams++;
teamsLocker.Unlock();
@@ -2055,6 +2066,11 @@ fork_team(void)
team->debug_info.flags |= atomic_get(&parentTeam->debug_info.flags)
& B_TEAM_DEBUG_INHERITED_FLAGS;
if (teamLimitReached) {
status = B_NO_MORE_TEAMS;
goto err1;
}
forkArgs = (arch_fork_arg*)malloc(sizeof(arch_fork_arg));
if (forkArgs == NULL) {
status = B_NO_MEMORY;
@@ -2185,6 +2201,8 @@ err1:
teamsLocker.Lock();
sTeamHash.Remove(team);
if (!teamLimitReached)
sUsedTeams--;
teamsLocker.Unlock();
sNotificationService.Notify(TEAM_REMOVED, team);
+22 -3
View File
@@ -1015,19 +1015,38 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel)
}
// We're going to make the thread live, now. The thread itself will take
// over a reference to its Thread object. We acquire another reference for
// our own use (and threadReference remains armed).
thread->AcquireReference();
// over a reference to its Thread object. We'll acquire another reference
// for our own use (and threadReference remains armed).
ThreadLocker threadLocker(thread);
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
SpinLocker threadHashLocker(sThreadHashLock);
// check the thread limit
if (sUsedThreads >= sMaxThreads) {
// Clean up the user_thread structure. It's a bit unfortunate that the
// Thread destructor cannot do that, so we have to do that explicitly.
threadHashLocker.Unlock();
schedulerLocker.Unlock();
user_thread* userThread = thread->user_thread;
thread->user_thread = NULL;
threadLocker.Unlock();
if (userThread != NULL)
team_free_user_thread(team, userThread);
return B_NO_MORE_THREADS;
}
// make thread visible in global hash/list
thread->visible = true;
sUsedThreads++;
scheduler_on_thread_init(thread);
thread->AcquireReference();
// Debug the new thread, if the parent thread required that (see above),
// or the respective global team debug flag is set. But only, if a
// debugger is installed for the team.