2

App crashes immediately after I attempt to login so it can’t a be a watchdog memory issue

Reason: _mh_execute_header App crashes upon attempting to make a network request using ASIHTTPRequest. Request never touches server. ASIHTTPRequest: I use -fno-objc-arc to omit ASIHTTPRequest from ARC.

I believe that the following call is causing my problems since my call never even touches the server when I make a request. Any help would be greatly appreciated!

Call:

NSDictionary *response = [[NetworkManager sharedManager] loginWithName:name password:pwd];

Method:

- (NSDictionary *)loginWithName:(NSString *)name password:(NSString *)pwd
{
    NSURL *url = [NSURL URLWithString:@"http://www.test.com/keys"];
    NSArray *values = [NSArray arrayWithObjects:@"iphone", @"iphone@test.com", name, pwd, nil];
    NSArray *keys = [NSArray arrayWithObjects:@"name", @"email", @"username", @"password", nil];
    NSDictionary *response = [self startNetworkPOSTRequestWithUrl:url 
                                                       postValues:values 
                                                          forKeys:keys];
    return response;
}

Stack Trace:

 Thread: Unknown Name (Crashed)
    0     libobjc.A.dylib                     0x37b9ef7e objc_msgSend + 21
    1     Test                          0x000dcda5 _mh_execute_header + 126373
    2     Test                          0x000dc4b9 _mh_execute_header + 124089
    3     Test                          0x000cd801 _mh_execute_header + 63489
    4     Test                          0x000ce39d _mh_execute_header + 66461
    5     Test                          0x000cf561 _mh_execute_header + 71009
    6     Test                          0x000d3e3d _mh_execute_header + 89661
    7     UIKit                               0x3334ccbd -[UITextField keyboardInput:shouldInsertText:isMarkedText:] + 148
    8     UIKit                               0x3334cc1f -[UIFieldEditor keyboardInput:shouldInsertText:isMarkedText:] + 94
    9     UIKit                               0x3334cbb9 -[UIKeyboardImpl callShouldInsertText:] + 108
    10   UIKit                               0x3334bb5b -[UIKeyboardImpl addInputString:fromVariantKey:] + 114
    11   UIKit                               0x3334bae1 -[UIKeyboardImpl handleStringInput:fromVariantKey:] + 164
    12   UIKit                               0x3334a775 -[UIKeyboardImpl handleKeyEvent:] + 1320
    13   UIKit                               0x334e48a3 -[UIKeyboardLayoutStar sendStringAction:forKey:isPopupVariant:] + 486
    14   UIKit                               0x33348dcd -[UIKeyboardLayoutStar touchUp:] + 3196
    15   UIKit                               0x333480fd -[UIKeyboardLayout touchesEnded:withEvent:] + 380
    16   UIKit                               0x3324b92b -[UIWindow _sendTouchesForEvent:] + 318
    17   UIKit                               0x3324b319 -[UIWindow sendEvent:] + 380
    18   UIKit                               0x33231695 -[UIApplication sendEvent:] + 356
    19   UIKit                               0x33230f3b _UIApplicationHandleEvent + 5826
    20   GraphicsServices                    0x373f022b PurpleEventCallback + 882
    21   CoreFoundation                      0x357d1523 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 38
    22   CoreFoundation                      0x357d14c5 __CFRunLoopDoSource1 + 140
    23   CoreFoundation                      0x357d0313 __CFRunLoopRun + 1370
    24   CoreFoundation                      0x357534a5 CFRunLoopRunSpecific + 300
    25   CoreFoundation                      0x3575336d CFRunLoopRunInMode + 104
    26   GraphicsServices                    0x373ef439 GSEventRunModal + 136
    27   UIKit                               0x3325fcd5 UIApplicationMain + 1080
    28   Test                          0x000bfc1b _mh_execute_header + 7195

Contents of the startNetworkPOSTRequestWithUrl method:

- (NSDictionary *)startNetworkPOSTRequestWithUrl:(NSURL *)url
                                      postValues:(NSArray *)values
                                         forKeys:(NSArray *)keys
{
    NSLog(@"saved user info: %@", values);
    __unsafe_unretained __block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
    __block NSDictionary *response;
    int num = [values count];
    __block BOOL success = YES;

    for (int i = 0; i < num; i++)
    {
        [request setPostValue:[values objectAtIndex:i] forKey:[keys objectAtIndex:i]];
    }

    [request setDelegate:self];
    [request setUseCookiePersistence:NO];
    [request setCompletionBlock:^{
        NSString *responseString = [request responseString];
        response = [responseString JSONValue];
    }];
    [request setFailedBlock:^{
        NSError *error = [request error];
        NSLog(@"\nError: %@", error.localizedDescription);
        NSString *responseString = [request responseString];
        NSLog(@"\nError Response: %@", responseString);
        NSLog(@"\nurl: %@",url);
        success = NO;
    }];
    [request startSynchronous];

    if (success == NO)
    {
        return nil;
    }

    if (![(NSString *)[response valueForKey:@"status"] isEqualToString:@"success"])
    {
        NSLog(@"response: %@",response);
        return nil;
    }

    return (NSDictionary *)[response valueForKey:@"response"];
}
chaselee
  • 326
  • 3
  • 6
  • Does this only happen with an Ad-Hoc build? Can we see the startNetworkPOSTRequestWithUrl call? – Randall Aug 21 '12 at 19:52

3 Answers3

2

I found another odd workaround that's solving some of my problems:

Under Target > Build Settings > Apple LLVM compiler 4.0 - Code Generation > Optimization Level I changed Ad Hoc Optimization to None - away from the default Fastest, Smallest [-Os] and this allows me to create a working ipa.

While this does provide a workaround it's less than ideal considering there may be other consequences of me doing no optimization.

But I do think this hints that some of my underlying problems are memory related - can anyone provide any insights into this?

Karoh
  • 2,390
  • 3
  • 23
  • 29
  • You're using ARC with everything except the ASIHTTPRequest lib, right? I feel like that could be the cause, since this looks to me like you're releasing an object that's already been released. EDIT: Just to clarify, you don't use ARC on AHR since they handle it themselves. – chaselee Aug 23 '12 at 02:19
  • Yeah I'm excluding ASIHTTPRequest from ARC. Also, even when I change the Optimization level to just "Fast" its still crashes. – Karoh Aug 23 '12 at 02:28
  • I've started a new question concerning the optimization issue: http://stackoverflow.com/questions/12101362/iphone-sigsegv-crash-with-any-level-of-optimization-using-arcasihttprequest – Karoh Aug 23 '12 at 23:31
1

You're doing a synchronous request, so you don't need the failure blocks or completion blocks. That will get rid of all of the __block stuff and make it a bit less weird memory wise.

- (IBAction)grabURL:(id)sender
{
  NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
  ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
  [request startSynchronous];
  NSError *error = [request error];
  if (!error) {
    NSString *response = [request responseString];
  }
}

I got that from the top of http://allseeing-i.com/ASIHTTPRequest/How-to-use

Randall
  • 14,691
  • 7
  • 40
  • 60
1

Thanks Randall. startSynchronous may be a bit of a misnomer. Here is the method definition:

- (void)startSynchronous
{
#if DEBUG_REQUEST_STATUS || DEBUG_THROTTLING
    ASI_DEBUG_LOG(@"[STATUS] Starting synchronous request %@",self);
#endif
    [self setSynchronous:YES];
    [self setRunLoopMode:ASIHTTPRequestRunLoopMode];
    [self setInProgress:YES];

    if (![self isCancelled] && ![self complete]) {
        [self main];
        while (!complete) {
            [[NSRunLoop currentRunLoop] runMode:[self runLoopMode] beforeDate:[NSDate distantFuture]];
        }
    }

    [self setInProgress:NO];
}
Karoh
  • 2,390
  • 3
  • 23
  • 29
  • 1
    startSynchronous blocks until the request is completed. All the information you need will be available by the time it finishes. – Randall Aug 21 '12 at 22:20
  • 1
    Ah good catch - I've switched that call to [request startAsynchronous]. and yet my response returns null. Any idea why that is? – Karoh Aug 22 '12 at 16:00
  • I think you're misunderstanding how ASIHTTPRequest works. Here's a gist trying to explain it a little better. https://gist.github.com/9f4fd7c1749b3ffe8d6e – Randall Aug 22 '12 at 21:20
  • So I've discovered that when I use startSynchronous everything is working well and that my problem lies elsewhere (see my other answer - even before implementing your gist - thanks by the way). How could my loginWithName and startNetworkPOSTRequest be altered to support startAsynchronous? I've read the docs and it looks like they are using blocks in the same way that I am. The problem though, I believe, are my return statements outside of the blocks - how do I get around that? – Karoh Aug 23 '12 at 02:54
  • 1
    I know you don't use returns, you're going to want a callback function in the blocks. I don't know how to do that though. @Randall can you add some color? – chaselee Aug 23 '12 at 03:17
  • In your login method you'll want to do the asynchronous request. Then, in your completion block you'll take care of whatever you need to do to show that the user logged in. – Randall Aug 23 '12 at 05:37