I received a strange crash report from a user.  User says it is not 
reproducible.  The way I read this, an infinite loop occurred in my 
NSPersistentDocument subclass of 
-canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo: when my code 
invoked super.  Here is the crash report.

Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   libSystem.B.dylib                   0x923020d2 tiny_malloc_from_free_list + 
5
1   libSystem.B.dylib                   0x92301301 szone_malloc_should_clear + 
263
2   libSystem.B.dylib                   0x923011a8 malloc_zone_malloc + 81
3   com.apple.CoreFoundation            0x90750f27 _CFArrayReplaceValues + 2647
4   com.apple.Foundation                0x92ebe4d7 -[NSCFArray 
insertObject:atIndex:] + 192
5   com.apple.Foundation                0x92ebe40f -[NSCFArray addObject:] + 68
6   com.apple.CoreFoundation            0x907b680c __NSArrayEnumerate + 1452
7   com.apple.CoreFoundation            0x907b6011 -[NSArray 
enumerateObjectsUsingBlock:] + 49
8   com.apple.AppKit                    0x908f6aea -[NSObjectParameterBinder 
_updateObject:observedController:observedKeyPath:context:] + 189
9   com.apple.AppKit                    0x908f6a25 -[NSObjectParameterBinder 
_observeValueForKeyPath:ofObject:context:] + 82
10  com.apple.Foundation                0x92ee3714 NSKeyValueNotifyObserver + 
372
11  com.apple.Foundation                0x92ee31b3 NSKeyValueDidChange + 377
12  com.apple.Foundation                0x92ec79ea 
-[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 127
13  com.mycompany.MyPrivateFramework    0x000f04f6 0x6000 + 959734
14  com.mycompany.MyPrivateFramework    0x000fa9d0 0x6000 + 1001936
15  com.mycompany.MyPrivateFramework    0x000faa14 0x6000 + 1002004
16  com.apple.AppKit                    0x90c68f2f -[NSDocumentController 
_closeDocumentsStartingWith:shouldClose:closeAllContext:] + 65
17  com.mycompany.MyPrivateFramework    0x000fa97e 0x6000 + 1001854
18  com.mycompany.MyPrivateFramework    0x000fa97e 0x6000 + 1001854
19  com.mycompany.MyPrivateFramework    0x000fa97e 0x6000 + 1001854
…
<snip out identical lines>
…
509 com.mycompany.MyPrivateFramework    0x000fa97e 0x6000 + 1001854
510 com.mycompany.MyPrivateFramework    0x000fa97e 0x6000 + 1001854
511 com.mycompany.MyPrivateFramework    0x000fa97e 0x6000 + 1001854

I believe that lines 0-12 simply show the innocent methods which happened to be 
executing when the stack limit was blown, and that the actual problem is the 
infinite loop in lines 13-511.

GDB says that the address 0x000fa97e 0x6000 is the line invoking super, at the 
end of my implementation shown below, as noted in the comment.  And I believe 
it, because according to the user's story, the crash did occur when he closed a 
document, and also, in typical infinite loop behavior, it took more than a few 
seconds for the crash dialog to appear.

How can there be an infinite loop invoking super in a method?  Looks like it 
was re-invoking itself instead of invoking super.

Jerry

- (void)canCloseDocumentWithDelegate:(id)delegate
                 shouldCloseSelector:(SEL)shouldCloseSelector
                         contextInfo:(void *)contextInfo {
   if ([[[self macster] autosaveUponClose] boolValue]) {
        // User has checked ON the 'autosave upon close' option
        // From the user's account, and my examination of his data, I believe
        // that this branch did *not* execute prior to the crash.  I'm
        // just including it for completeness

        // This code was taken from the second-last post in this thread:
        // 
http://www.cocoabuilder.com/archive/cocoa/153196-customizing-save-behavior-in-docbased-apps.html?q=%22Don't+Save%22+save+automatically#153196

        // Only do this if the document has been previously saved
        if ([self fileURL]) {
            NSError* error ;
            BOOL ok =[[self managedObjectContext] save:&error] ;
            if (!ok) {
                [self alertError:error] ;
            }

            // Clear change count to prevent the super call from invoking save 
dialog
            [self updateChangeCount:NSChangeCleared] ;
        }
    }
    
    BOOL closeNow = YES ;

    if (NSApp && !m_skipAskExportDuringNextClose) {
        // From the user's account, and my examination of his data, I believe
        // that this branch did *not* execute prior to the crash.  I'm
        // just including it for completeness
 
       NSMutableArray* unexportedActiveExporters = [[NSMutableArray alloc] 
init] ;
        for (Exporter* exporter in [[self macster] activeExportersOrdered]) {
            if ([exporter isActive]) {
                if ([[exporter ixportCount] integerValue] == 0) {
                    [unexportedActiveExporters addObject:exporter] ;
                    break ;
                }
            }
        }
        if ([unexportedActiveExporters count] > 0) {
            NSString* and = [NSString localize:@"andEndList"] ;
            NSString* list = [unexportedActiveExporters 
listValuesForKey:@"displayName"
                                                             conjunction:and
                                                              truncateTo:0] ;
            NSString* msg = [NSString localizeFormat:
                             @"imex_exportShouldX",
                             list] ;
            SSYAlert* alert = [SSYAlert alert] ;
            [alert setSmallText:msg] ;
            [alert setButton1Title:[[BkmxBasis sharedBasis] 
labelExportAndClose]] ;
            [alert setButton2Title:[[BkmxBasis sharedBasis] labelCancel]] ;
            [alert setButton3Title:[[BkmxBasis sharedBasis] labelClose]] ;
            
            NSArray* invocations ;
            invocations = [NSArray arrayWithObjects:
                  [NSInvocation invocationWithTarget:self  // "Export and Close"
                                            
selector:@selector(exportAndCloseToExporters:)
                                     retainArguments:YES
                                   
argumentAddresses:&unexportedActiveExporters],
                  [NSNull null],  // "Cancel"
                  [NSInvocation invocationWithTarget:self  // "Close"
                                            selector:@selector(close)
                                     retainArguments:YES
                                   argumentAddresses:NULL],
                  nil] ;
            
            m_skipAskExportDuringNextClose = YES ;
            
            [self runModalSheetAlert:alert
                           iconStyle:SSYAlertIconInformational
                       modalDelegate:[SSYSheetEnder class]
                      
didEndSelector:@selector(didEndGenericSheet:returnCode:invocations:)
                         contextInfo:[invocations retain]] ;
            closeNow = NO ;
        }

        [unexportedActiveExporters release] ;
    }
    
    if (closeNow) {
        // 20101120  The following line crashed with an infinite loop for user 
John Doe.
        [super canCloseDocumentWithDelegate:delegate
                        shouldCloseSelector:shouldCloseSelector
                                contextInfo:contextInfo] ;
    }
    
    m_skipAskExportDuringNextClose = NO ;
}

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to