[haiku-commits] haiku: hrev45811 - src/system/kernel

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 2 Jul 2013 02:04:01 +0200 (CEST)

hrev45811 adds 2 changesets to branch 'master'
old head: a97ff1bb60f6c3adddc121296175de58cb3f632c
new head: 2eb2b522bf0b3533a7a35bc5fa8d1caa0d2573d2
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=2eb2b52+%5Ea97ff1b

----------------------------------------------------------------------------

cbcde3b: kernel team.cpp: fix unbalanced io_context ref management
  
  ... in case of team creation error. Once assigned to Team::io_context
  the Team object takes responsibility of the I/O context object and
  releases the reference on destruction. load_image_internal() and
  fork_team() were thus releasing one reference too many.
  
  Fixes #9851.

2eb2b52: 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.

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

----------------------------------------------------------------------------

2 files changed, 46 insertions(+), 12 deletions(-)
src/system/kernel/team.cpp   | 33 ++++++++++++++++++++++++---------
src/system/kernel/thread.cpp | 25 ++++++++++++++++++++++---

############################################################################

Commit:      cbcde3ba8058d84d86d3a36b1ebbec37ed1f35ea
URL:         http://cgit.haiku-os.org/haiku/commit/?id=cbcde3b
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Mon Jul  1 23:16:02 2013 UTC

Ticket:      https://dev.haiku-os.org/ticket/9851

kernel team.cpp: fix unbalanced io_context ref management

... in case of team creation error. Once assigned to Team::io_context
the Team object takes responsibility of the I/O context object and
releases the reference on destruction. load_image_internal() and
fork_team() were thus releasing one reference too many.

Fixes #9851.

----------------------------------------------------------------------------

diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp
index 1212b62..abd52ed 100644
--- a/src/system/kernel/team.cpp
+++ b/src/system/kernel/team.cpp
@@ -503,7 +503,8 @@ Team::~Team()
        // get rid of all associated data
        PrepareForDeletion();
 
-       vfs_put_io_context(io_context);
+       if (io_context != NULL)
+               vfs_put_io_context(io_context);
        delete_owned_ports(this);
        sem_delete_owned_sems(this);
 
@@ -1752,7 +1753,7 @@ load_image_internal(char**& _flatArgs, size_t 
flatArgsSize, int32 argCount,
        status = VMAddressSpace::Create(team->id, USER_BASE, USER_SIZE, false,
                &team->address_space);
        if (status != B_OK)
-               goto err3;
+               goto err2;
 
        // create the user data area
        status = create_team_user_data(team);
@@ -1814,8 +1815,6 @@ err5:
        delete_team_user_data(team);
 err4:
        team->address_space->Put();
-err3:
-       vfs_put_io_context(team->io_context);
 err2:
        free_team_arg(teamArgs);
 err1:
@@ -2075,7 +2074,7 @@ fork_team(void)
                        parentTeam->realtime_sem_context);
                if (team->realtime_sem_context == NULL) {
                        status = B_NO_MEMORY;
-                       goto err25;
+                       goto err2;
                }
        }
 
@@ -2170,8 +2169,6 @@ err4:
        team->address_space->RemoveAndPut();
 err3:
        delete_realtime_sem_context(team->realtime_sem_context);
-err25:
-       vfs_put_io_context(team->io_context);
 err2:
        free(forkArgs);
 err1:

############################################################################

Revision:    hrev45811
Commit:      2eb2b522bf0b3533a7a35bc5fa8d1caa0d2573d2
URL:         http://cgit.haiku-os.org/haiku/commit/?id=2eb2b52
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Mon Jul  1 23:55:04 2013 UTC

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.

----------------------------------------------------------------------------

diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp
index abd52ed..c5b0f7e 100644
--- a/src/system/kernel/team.cpp
+++ b/src/system/kernel/team.cpp
@@ -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);
diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp
index 7ac994c..7e29df2 100644
--- a/src/system/kernel/thread.cpp
+++ b/src/system/kernel/thread.cpp
@@ -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.


Other related posts:

  • » [haiku-commits] haiku: hrev45811 - src/system/kernel - ingo_weinhold