Only invalidate+release the old status timer when the new one is scheduled - pre…
…vents a crash for async requests when only the timer is retaining the request
Showing
1 changed file
with
14 additions
and
4 deletions
@@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
21 | #import "ASIInputStream.h" | 21 | #import "ASIInputStream.h" |
22 | 22 | ||
23 | // Automatically set on build | 23 | // Automatically set on build |
24 | -NSString *ASIHTTPRequestVersion = @"v1.2-65 2010-01-05"; | 24 | +NSString *ASIHTTPRequestVersion = @"v1.2-66 2010-01-05"; |
25 | 25 | ||
26 | NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; | 26 | NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; |
27 | 27 | ||
@@ -1021,7 +1021,7 @@ static BOOL isiPhoneOS2; | @@ -1021,7 +1021,7 @@ static BOOL isiPhoneOS2; | ||
1021 | // Record when the request started, so we can timeout if nothing happens | 1021 | // Record when the request started, so we can timeout if nothing happens |
1022 | [self setLastActivityTime:[NSDate date]]; | 1022 | [self setLastActivityTime:[NSDate date]]; |
1023 | 1023 | ||
1024 | - [[self statusTimer] invalidate]; | 1024 | + |
1025 | [self setStatusTimer:[NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(updateStatus:) userInfo:nil repeats:YES]]; | 1025 | [self setStatusTimer:[NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(updateStatus:) userInfo:nil repeats:YES]]; |
1026 | 1026 | ||
1027 | // If we're running asynchronously on the main thread, the runloop will already be running and we can return control | 1027 | // If we're running asynchronously on the main thread, the runloop will already be running and we can return control |
@@ -1032,6 +1032,17 @@ static BOOL isiPhoneOS2; | @@ -1032,6 +1032,17 @@ static BOOL isiPhoneOS2; | ||
1032 | } | 1032 | } |
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | +- (void)setStatusTimer:(NSTimer *)timer | ||
1036 | +{ | ||
1037 | + // We must invalidate the old timer here, not before we've created and scheduled a new timer | ||
1038 | + // This is because the timer may be the only thing retaining an asynchronous request | ||
1039 | + if (timer != [self statusTimer]) { | ||
1040 | + [[self statusTimer] invalidate]; | ||
1041 | + [[self statusTimer] release]; | ||
1042 | + } | ||
1043 | + statusTimer = [timer retain]; | ||
1044 | +} | ||
1045 | + | ||
1035 | - (void)performRedirect | 1046 | - (void)performRedirect |
1036 | { | 1047 | { |
1037 | [[self cancelledLock] lock]; | 1048 | [[self cancelledLock] lock]; |
@@ -1055,8 +1066,7 @@ static BOOL isiPhoneOS2; | @@ -1055,8 +1066,7 @@ static BOOL isiPhoneOS2; | ||
1055 | - (void)updateStatus:(NSTimer*)timer | 1066 | - (void)updateStatus:(NSTimer*)timer |
1056 | { | 1067 | { |
1057 | [self checkRequestStatus]; | 1068 | [self checkRequestStatus]; |
1058 | - if ([self complete] || [self error]) { | 1069 | + if (![self inProgress]) { |
1059 | - [timer invalidate]; | ||
1060 | [self setStatusTimer:nil]; | 1070 | [self setStatusTimer:nil]; |
1061 | CFRunLoopStop(CFRunLoopGetCurrent()); | 1071 | CFRunLoopStop(CFRunLoopGetCurrent()); |
1062 | } | 1072 | } |
-
Please register or login to post a comment