mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
try to cope better with apps which leak autorelease pools.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@33099 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
afc2ef7de8
commit
e32626abe7
2 changed files with 66 additions and 10 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,7 +1,16 @@
|
|||
2011-05-24 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSAutoreleasePool.m:
|
||||
Try to better cope with bad code which leaks autorelease pools.
|
||||
1. check number of pools in thread when creating a new one, and
|
||||
raise an exception if too many are created.
|
||||
2. when deallocating a pool, avoid recursively deallocating child
|
||||
pools so that a large number of pools won't cause stack overflow.
|
||||
|
||||
2011-05-23 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSBundle.m:
|
||||
Fixe to resolve links and standardize path to current executable.
|
||||
Fix to resolve links and standardize path to current executable.
|
||||
|
||||
2011-05-22 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
|
|
|
@ -156,6 +156,11 @@ static NSAutoreleasePool *pool = nil;
|
|||
return;
|
||||
}
|
||||
|
||||
+ (void) setPoolNumberThreshhold: (unsigned)c
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else
|
||||
|
@ -166,9 +171,13 @@ static NSAutoreleasePool *pool = nil;
|
|||
static BOOL autorelease_enabled = YES;
|
||||
|
||||
/* When the _released_count of a pool gets over this value, we raise
|
||||
an exception. This can be adjusted with -setPoolCountThreshhold */
|
||||
an exception. This can be adjusted with +setPoolCountThreshhold */
|
||||
static unsigned pool_count_warning_threshhold = UINT_MAX;
|
||||
|
||||
/* When the number of pools in a thread gets over this value, we raise
|
||||
an exception. This can be adjusted with +setPoolNumberThreshhold */
|
||||
static unsigned pool_number_warning_threshhold = 10000;
|
||||
|
||||
/* The size of the first _released array. */
|
||||
#define BEGINNING_POOL_SIZE 32
|
||||
|
||||
|
@ -305,10 +314,25 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
*/
|
||||
{
|
||||
struct autorelease_thread_vars *tv = ARP_THREAD_VARS;
|
||||
unsigned level = 0;
|
||||
_parent = tv->current_pool;
|
||||
if (_parent)
|
||||
_parent->_child = self;
|
||||
{
|
||||
NSAutoreleasePool *pool = _parent;
|
||||
|
||||
while (nil != pool)
|
||||
{
|
||||
level++;
|
||||
pool = pool->_parent;
|
||||
}
|
||||
_parent->_child = self;
|
||||
}
|
||||
tv->current_pool = self;
|
||||
if (level > pool_number_warning_threshhold)
|
||||
{
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Too many (%u) autorelease pools ... leaking them?", level];
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -504,14 +528,32 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
{
|
||||
volatile struct autorelease_array_list *released;
|
||||
|
||||
/* If there are NSAutoreleasePool below us in the stack of
|
||||
NSAutoreleasePools, then deallocate them also. The (only) way we
|
||||
could get in this situation (in correctly written programs, that
|
||||
don't release NSAutoreleasePools in weird ways), is if an
|
||||
exception threw us up the stack. */
|
||||
while (_child != nil)
|
||||
/* If there are NSAutoreleasePool below us in the list of
|
||||
* NSAutoreleasePools, then deallocate them also.
|
||||
* The (only) way we could get in this situation (in correctly
|
||||
* written programs, that don't release NSAutoreleasePools in
|
||||
* weird ways), is if an exception threw us up the stack.
|
||||
* However, if a program has leaked pools we may be deallocating
|
||||
* a pool with LOTS of children. To avoid stack overflow we
|
||||
* therefore deallocate children starting with the oldest first.
|
||||
*/
|
||||
if (nil != _child)
|
||||
{
|
||||
[_child dealloc];
|
||||
NSAutoreleasePool *pool = _child;
|
||||
|
||||
/* Find other end of linked list ... oldest child.
|
||||
*/
|
||||
while (nil != pool->_child)
|
||||
{
|
||||
pool = pool->_child;
|
||||
}
|
||||
/* Deallocate the children in the list.
|
||||
*/
|
||||
while (pool != self)
|
||||
{
|
||||
pool = pool->_parent;
|
||||
[pool->_child dealloc];
|
||||
}
|
||||
}
|
||||
|
||||
/* Take the object out of the released list just before releasing it,
|
||||
|
@ -634,5 +676,10 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
pool_count_warning_threshhold = c;
|
||||
}
|
||||
|
||||
+ (void) setPoolNumberThreshhold: (unsigned)c
|
||||
{
|
||||
pool_number_warning_threshhold = c;
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue