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