diff --git a/ChangeLog b/ChangeLog index 11807742a..10c8c3e88 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-02-01 Richard Frith-Macdonald + + * Source/NSAutoreleasePool.m: + * Source/NSThread.m: + Tweaks to try and get default thread correctly terminated on exit. + 2010-01-30 Fred Kiefer * Source/NSPropertyList.m (GSBinaryPLParser -rootObject, diff --git a/Source/NSAutoreleasePool.m b/Source/NSAutoreleasePool.m index e1975070c..1ea791f13 100644 --- a/Source/NSAutoreleasePool.m +++ b/Source/NSAutoreleasePool.m @@ -385,14 +385,14 @@ static IMP initImp; */ while (_child != nil || _released_count > 0) { - volatile struct autorelease_array_list *released = _released_head; + 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. */ - if (_child != nil) + while (_child != nil) { [_child dealloc]; } @@ -401,6 +401,7 @@ static IMP initImp; * so if we are doing "double_release_check"ing, then * autoreleaseCountForObject: won't find the object we are currently * releasing. */ + released = _released_head; while (released != 0) { id *objects = (id*)(released->objects); @@ -457,6 +458,7 @@ static IMP initImp; NSZoneFree(NSDefaultMallocZone(), a); a = n; } + _released = _released_head = 0; [super dealloc]; } @@ -473,12 +475,25 @@ static IMP initImp; NSAutoreleasePool *pool; tv = &(((TInfo)thread)->_autorelease_vars); + + /* First release any objects in the pool... bearing in mind that + * releasing any object could cause other objects to be added to + * the pool. + */ + pool = tv->current_pool; + while (pool) + { + [pool emptyPool]; + pool = pool->_parent; + } + + /* Now free the memory (we have finished usingthe pool). + */ pool = tv->current_pool; while (pool) { NSAutoreleasePool *p = pool->_parent; - [pool emptyPool]; [pool _reallyDealloc]; pool = p; } diff --git a/Source/NSThread.m b/Source/NSThread.m index 694a521a0..b228b89e9 100644 --- a/Source/NSThread.m +++ b/Source/NSThread.m @@ -313,7 +313,14 @@ static pthread_key_t thread_object_key; */ static void exitedThread(void *thread) { - if (thread != defaultThread) + if (thread == defaultThread) + { + NSThread *t = defaultThread; + + defaultThread = nil; + [t dealloc]; + } + else { fprintf(stderr, "WARNING thread %p terminated without calling +exit!\n", thread); @@ -447,6 +454,7 @@ static void setThreadForCurrentThread(NSThread *t) if (t == nil) { t = [self new]; + t->_active = YES; pthread_setspecific(thread_object_key, t); [thread_creation_lock unlock]; return YES; @@ -503,7 +511,7 @@ static void setThreadForCurrentThread(NSThread *t) userInfo: nil]; [(GSRunLoopThreadInfo*)t->_runLoopInfo invalidate]; - + RELEASE(t); #if GS_WITH_GC && defined(HAVE_GC_REGISTER_MY_THREAD) GC_unregister_my_thread(); #endif @@ -632,12 +640,6 @@ static void setThreadForCurrentThread(NSThread *t) - (void) dealloc { - if (self == defaultThread) - { - [self retain]; - [NSException raise: NSInternalInconsistencyException - format: @"Deallocating the default thread is not allowed!"]; - } if (_active == YES) { [NSException raise: NSInternalInconsistencyException