EXC_BAD_ACCESS in RKResponse in case of an unreachable URL #628

Closed
thomas-goerlich opened this Issue Mar 28, 2012 · 12 comments

Comments

Projects
None yet
9 participants

The following behaviour happens in the current development branch.

I get an EXC_BAD_ACCESS in RKResponse (RKResponse.m)

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    _failureError = [error retain];
    [_request invalidateTimeoutTimer];
    [_request didFailLoadWithError:_failureError];        // <---- EXC_BAD_ACCESS here
}

if the baseURL is unreachable. This only happens in the RKClient/RKRequest methods. If i use the ObjectManager/CoreData functions i get the expected error message in

- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error

I can reproduce this behaviour in the RKCatalog example if i change the baseURL in the AppDelegate to something like:

gRKCatalogBaseURL = [[NSURL alloc] initWithString:@"http://domain.tld"];

If i run the app and open the RKRequestQueueExample i get the EXC_BAD_ACCESS. Opening the RKRelationshipMappingExample on the other hand runs as expected and shows the UIAlertView.

Owner

blakewatters commented Mar 29, 2012

Thanks for the note. Will take a look.

It seems like the _request variable gets released to often. If i retain it, it works, but it might result in objects that are not needed anymore with an release count > 0.

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    _failureError = [error retain];
    [_request retain];         // <---- adding a retain to the request "fixed" the problem
    [_request invalidateTimeoutTimer];
    [_request didFailLoadWithError:_failureError];
}

We've run into the same issue.

I think the issue is that the timer retains the _request and when the timer is invalidated, the _request is released.

We are using the following as a workaround:


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    RKResponseIgnoreDelegateIfCancelled();
    _failureError = [error retain];
    [_request retain];
    [_request invalidateTimeoutTimer];
    [_request didFailLoadWithError:_failureError];
    [_request release];
}

sendhil commented Apr 20, 2012

I'm hitting the same issue. If I make a request and the server is down I'll get the EXC_BAD_ACCESS, it happens usually at the start of my app when a request is made. It also happens if I turn the server off while the app is loaded and then make a request.

Owner

blakewatters commented Apr 20, 2012

I have moved this back to 0.10.1 milestone for review soon.

Contributor

sprynmr commented Apr 24, 2012

Ah. Just ran into this. Good to see the potential fix.

Ran into this one as well. Thanks for the workaround @echamberlain

aporat commented May 4, 2012

@echamberlain thanks!

Owner

blakewatters commented May 4, 2012

I am looking into this. After being unable to reproduce in a unit test, I have fired up the RKCatalog app as outlined in the original report. The issue seems to be not that the request is being over-released, but that the queue is re-sending it after it fails. Should have it all sorted out shortly.

Owner

blakewatters commented May 4, 2012

Got it. Confirmed that on failure case, the request was being resent because it was removed from the loading collection but not from the queue itself. This caused it to be dispatched again with an unbalanced retain count.

I have a similar error, caused by the same issue. I invalidate an NSTimer and move back from one MVC to another and I constantly get an EXC_BAD_ACCESS here:

  • (void)connection:(NSURLConnection _)connection didReceiveData:(NSData )data {
    [_body appendData:data];
    [request invalidateTimeoutTimer];
    /
    begin error line _/ if ([[_request delegate] respondsToSelector:@selector(request:didReceivedData:totalBytesReceived:totalBytesExectedToReceive:)]) { /_end error line
    /
    [[_request delegate] request:_request didReceivedData:[data length] totalBytesReceived:[_body length] totalBytesExectedToReceive:_httpURLResponse.expectedContentLength];
    }
    }

patr1ck commented May 14, 2012

I'm getting a similar crash, but instead inside RKRequest's didFailLoadWithError:(NSError*)error method.

The last line,

[[NSNotificationCenter defaultCenter] postNotificationName:RKRequestDidFinishLoadingNotification object:self];

is causing the overrelease. This is as of 7656a96.

blakewatters added a commit that referenced this issue May 17, 2012

Fixes to ensure failed requests are not resent. refs #628, fixes #744,
…closes #720

Additional changes and test coverage to handle the case of loading an invalid URL
or otherwise immediately encountering an error condition:

* Restores use of removeLoadingRequest: within the queue
* Updates fragile tests to ensure better coverage for error cases
* Sets isLoaded to YES during error callbacks to prevent duplicated dispatching
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment