From 52f2105eb1ce1eac1ee9cc6a9adaafee1f9710a0 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 24 Dec 2007 17:31:52 +0000 Subject: [PATCH] Fix memory leak. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25779 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 2 ++ Source/NSThread.m | 89 ++++++++++++++++++++++++++++++----------------- 2 files changed, 59 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 495d1f241..88a3f7c42 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ * Source/NSRunLoop.m: Perhaps a bit paranoid, but alter to recheck all timers after any timer is fired, so we ar sure to pick up any changes done to timer fire dates during the firing of a timer. + * Source/NSThread.m: Fix memory leak and correct thread startup + semantics to be like MacOS-X I hope. 2007-12-22 Richard Frith-Macdonald diff --git a/Source/NSThread.m b/Source/NSThread.m index 7580d7139..2b4c89768 100644 --- a/Source/NSThread.m +++ b/Source/NSThread.m @@ -538,11 +538,6 @@ gnustep_base_thread_callback(void) { NSThread *thread; - /* - * Make sure the notification is posted BEFORE the new thread starts. - */ - gnustep_base_thread_callback(); - /* * Create the new thread. */ @@ -551,14 +546,8 @@ gnustep_base_thread_callback(void) selector: aSelector object: anArgument]; - /* - * Have the runtime detach the thread - */ - if (objc_thread_detach(@selector(start), thread, nil) == NULL) - { - [NSException raise: NSInternalInconsistencyException - format: @"Unable to detach thread (unknown error)"]; - } + [thread start]; + RELEASE(thread); } @@ -803,7 +792,42 @@ gnustep_base_thread_callback(void) - (void) main { + if (_active == NO) + { + [NSException raise: NSInternalInconsistencyException + format: @"[%@-$@] called on inactive thread", + NSStringFromClass([self class]), + NSStringFromSelector(_cmd)]; + } + if (objc_thread_get_data() != nil) + { + [NSException raise: NSInternalInconsistencyException + format: @"[%@-$@] called on running thread", + NSStringFromClass([self class]), + NSStringFromSelector(_cmd)]; + } + + /* + * We are running in the new thread - so we store ourself in the thread + * dictionary and release ourself - thus, when the thread exits, we will + * be deallocated cleanly. + */ + objc_thread_set_data(self); + + /* + * Let observers know a new thread is starting. + */ + if (nc == nil) + { + nc = RETAIN([NSNotificationCenter defaultCenter]); + } + [nc postNotificationName: NSThreadDidStartNotification + object: self + userInfo: nil]; + [_target performSelector: _selector withObject: _arg]; + + [NSThread exit]; } - (NSString*) name @@ -829,27 +853,28 @@ gnustep_base_thread_callback(void) - (void) start { - /* - * We are running in the new thread - so we store ourself in the thread - * dictionary and release ourself - thus, when the thread exits, we will - * be deallocated cleanly. - */ - objc_thread_set_data(self); - _active = YES; - - /* - * Let observers know a new thread is starting. - */ - if (nc == nil) + if (_active == NO) { - nc = RETAIN([NSNotificationCenter defaultCenter]); - } - [nc postNotificationName: NSThreadDidStartNotification - object: self - userInfo: nil]; + /* Make sure the notification is posted BEFORE the new thread starts. + */ + gnustep_base_thread_callback(); - [self main]; - [NSThread exit]; + /* The thread must persist until if finishes executing. + */ + RETAIN(self); + + /* Mark the thread as active whiul it's running. + */ + _active = YES; + + if (objc_thread_detach(@selector(main), self, nil) == NULL) + { + _active = NO; + RELEASE(self); + [NSException raise: NSInternalInconsistencyException + format: @"Unable to detach thread (unknown error)"]; + } + } } /**