Skip to content

Crash in IMBParser populateNewNode:likeOldNode:options: #97

@robert-plasq

Description

@robert-plasq

We've got a user who's able to reliably crash the app in the iMB code:

Crashed Thread:  9  Dispatch queue: NSOperationQueue 0xc9584d0

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000006c6f4665

Application Specific Information:
objc_msgSend() selector name: identifier

Thread 9 Crashed:: Dispatch queue: NSOperationQueue 0xc9584d0
0   libobjc.A.dylib                 0x99a054a4 objc_msgSend + 20
1   com.karelia.iMedia              0x004300d6 -[IMBParser populateNewNode:likeOldNode:options:] + 260
2   com.karelia.iMedia              0x00430907 -[IMBFolderParser nodeWithOldNode:options:error:] + 1028
3   com.karelia.iMedia              0x0043433b -[IMBCreateNodeOperation main] + 138
4   com.apple.Foundation            0x95691fec -[__NSOperationInternal _start:] + 702
5   com.apple.Foundation            0x95691d21 -[NSOperation start] + 71
6   com.apple.Foundation            0x95691c48 __NSOQSchedule_f + 50
7   libdispatch.dylib               0x9879be21 _dispatch_async_redirect_invoke + 158
8   libdispatch.dylib               0x98799467 _dispatch_root_queue_drain + 257
9   libdispatch.dylib               0x9879a732 _dispatch_worker_thread2 + 39
10  libsystem_pthread.dylib         0x98f3ddab _pthread_wqthread + 336
11  libsystem_pthread.dylib         0x98f41cce start_wqthread + 30

Our theory is that the oldSubNodes has been released in another thread and there's also this (from a different crash report):

Application Specific Information:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSTreeControllerTreeNode identifier]: unrecognized selector sent to instance 0x1f32d80'

Application Specific Backtrace 1:
0   CoreFoundation                      0x926be6b1 __raiseError + 193
1   libobjc.A.dylib                     0x90885091 objc_exception_throw + 162
2   CoreFoundation                      0x926c2ef3 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3   CoreFoundation                      0x9260e802 ___forwarding___ + 1010
4   CoreFoundation                      0x9260e3ee _CF_forwarding_prep_0 + 14
5   iMedia                              0x004300d6 -[IMBParser populateNewNode:likeOldNode:options:] + 260
6   iMedia                              0x00430907 -[IMBFolderParser nodeWithOldNode:options:error:] + 1028
7   iMedia                              0x0043433b -[IMBCreateNodeOperation main] + 138
8   Foundation                          0x99f40fec -[__NSOperationInternal _start:] + 702
9   Foundation                          0x99f40d21 -[NSOperation start] + 71
10  Foundation                          0x99f40c48 __NSOQSchedule_f + 50
11  libdispatch.dylib                   0x924fbe21 _dispatch_async_redirect_invoke + 158
12  libdispatch.dylib                   0x924f73a6 _dispatch_client_callout + 50
13  libdispatch.dylib                   0x924f9467 _dispatch_root_queue_drain + 257
14  libdispatch.dylib                   0x924fa732 _dispatch_worker_thread2 + 39
15  libsystem_pthread.dylib             0x95974dab _pthread_wqthread + 336
16  libsystem_pthread.dylib             0x95978cce start_wqthread + 30

All of which makes us think that this:

        // Do an "atomic" replace of the changed nodes array, thus only causing a single KVO notification. 
        // Please note the strange line setSubNodes:nil, which is a workaround for an nasty crashing bug deep  
        // inside NSTreeController, where we get a zombie NSTreeControllerTreeNode is some cases. Apparently 
        // the NSTreeController is very particular about us replacing the whole array in one go (maybe that 
        // isn't entirely KVO compliant), and it gets confused with its NSTreeControllerTreeNode objects.
        // The extra line (setting the array to nil) seems to clear out all NSTreeControllerTreeNodes and
        // then they get rebuilt with the next line. Until we rework our own stuff, we'll stick with this 
        // workaround...

        if (parentNode)
        {
            [parentNode setSubNodes:nil];       // Important workaround. Do not remove!
            [parentNode setSubNodes:nodes];
        }
        else
        {
            [self setRootNodes:nodes];
        }

is still causing trouble?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions