From 8bd01772921c7b97a577fcbe915234550879d95e Mon Sep 17 00:00:00 2001 From: rfm Date: Sat, 25 Sep 2010 21:28:07 +0000 Subject: [PATCH] Make firing of timers more robust git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@31420 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 6 +++++ Source/NSTimer.m | 63 ++++++++++++++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50e36820a..54b37a9f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-09-25 Richard Frith-Macdonald + + * Source/NSTimer.m: ([-fire]) make firing more robust by retaining + the target so it cannot be deallocated while we are performing a + method on it. Do nothing if timer is already invalidated. + 2010-09-24 Richard Frith-Macdonald * Source/NSCharacterSet.m: Build using the faster but more memory diff --git a/Source/NSTimer.m b/Source/NSTimer.m index 7db763216..6a8dceaab 100644 --- a/Source/NSTimer.m +++ b/Source/NSTimer.m @@ -224,36 +224,51 @@ static Class NSDate_class; */ - (void) fire { - if (_selector == 0) + id target; + + /* We retain the target so it won't be deallocated while we are using it + * (if this timer gets invalidated while we are firing). + */ + target = [_target retain]; + + /* We check that we have not been invalidated before we fire. + */ + if (NO == _invalidated) { - NS_DURING + if (_selector == 0) { - [(NSInvocation*)_target invoke]; + NS_DURING + { + [(NSInvocation*)target invoke]; + } + NS_HANDLER + { + NSLog(@"*** NSTimer ignoring exception '%@' (reason '%@') " + @"raised during posting of timer with target %p " + @"and selector '%@'", + [localException name], [localException reason], target, + NSStringFromSelector([target selector])); + } + NS_ENDHANDLER } - NS_HANDLER + else { - NSLog(@"*** NSTimer ignoring exception '%@' (reason '%@') " - @"raised during posting of timer with target %p and selector '%@'", - [localException name], [localException reason], _target, - NSStringFromSelector([_target selector])); + NS_DURING + { + [target performSelector: _selector withObject: self]; + } + NS_HANDLER + { + NSLog(@"*** NSTimer ignoring exception '%@' (reason '%@') " + @"raised during posting of timer with target %p and " + @"selector '%@'", + [localException name], [localException reason], target, + NSStringFromSelector(_selector)); + } + NS_ENDHANDLER } - NS_ENDHANDLER - } - else - { - NS_DURING - { - [_target performSelector: _selector withObject: self]; - } - NS_HANDLER - { - NSLog(@"*** NSTimer ignoring exception '%@' (reason '%@') " - @"raised during posting of timer with target %p and selector '%@'", - [localException name], [localException reason], _target, - NSStringFromSelector(_selector)); - } - NS_ENDHANDLER } + [target release]; if (_repeats == NO) {