0

Setting: In my app I have a Map with a lot of annotations. These annotations are displayed in cluster form, where the data is loaded from a server.

To create the clusters, the annotation DB is queried using a NSOperationQueue with the following properties:

qualityOfService = NSQualityOfServiceUtility;
maxConcurrentOperationCount = 1;

To add an operation I do the following:

- (void)updateAfterServerReturns {
    [_q cancelAllOperations];

    NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock: ^{
        __weak typeof(self) weakSelf = self;
       [weakSelf myOperation]
    }];

    if(operation) {
        @autoreleasepool {
        [_q addOperation:operation];
        }
    }
}
- (void)myOperation {
   //retrieve data, then update map
   __weak typeof(self) weakSelf = self;  
  [weakSelf updateMap];
}

- (void)updateMap {
    __weak typeof(self) weakSelf = self;
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  //update
   }];
}

Problem: As the user moves around, and the information from the server returns, I get the following crash enqueued from com.apple.main-thread(Thread 1) which violently stops everything. The crash doesn't occur every time, but often enough to be unacceptable.

Anybody has any suggestions? Thanks!

Crash Details

in log:

2015-12-06 23:34:31.215 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(0x184450f48 0x199003f80 0x18433a754 0x100224af8 0x100119c18 0x100119ca4 0x100119c84 0x100119cd0 0x100119c64 0x100119cd0 0x100119ca4 0x100119cd0 0x100119c64 0x100119c84 0x100223b9c 0x1003d50c0 0x185378374 0x1852cb1a0 0x1852bb3e8 0x18537a768 0x100e2dc68 0x100e3a780 0x100e31958 0x100e3c898 0x100e3c590 0x199a35470 0x199a35020)
libc++abi.dylib: terminating with uncaught exception of type NSException
(Recorded Frame) 

stepping through Thread in which crash occurs, these are some:

libsystem_kernel.dylib`__pthread_kill:
0x19996f138 <+0>:  movz   x16, #0x148
0x19996f13c <+4>:  svc    #0x80
->  0x19996f140 <+8>:  b.lo   0x19996f158               ; <+32>
 0x19996f144 <+12>: stp    x29, x30, [sp, #-16]!
    0x19996f148 <+16>: mov    x29, sp
    0x19996f14c <+20>: bl     0x199956140               ; cerror_nocancel
    0x19996f150 <+24>: mov    sp, x29
    0x19996f154 <+28>: ldp    x29, x30, [sp], #16
    0x19996f158 <+32>: ret    

libdispatch.dylib`_dispatch_call_block_and_release:
    0x100e2dc90 <+0>:  stp    x20, x19, [sp, #-32]!
    0x100e2dc94 <+4>:  stp    x29, x30, [sp, #16]
    0x100e2dc98 <+8>:  add    x29, sp, #16
    0x100e2dc9c <+12>: mov    x19, x0
    0x100e2dca0 <+16>: ldr    x8, [x19, #16]
    0x100e2dca4 <+20>: blr    x8
->  0x100e2dca8 <+24>: mov    x0, x19
    0x100e2dcac <+28>: ldp    x29, x30, [sp, #16]
    0x100e2dcb0 <+32>: ldp    x20, x19, [sp], #32
    0x100e2dcb4 <+36>: b      0x100e59fec               ; symbol stub for: _Block_release

more details:

Foundation`__NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__:
    0x185378364 <+0>:  stp    x29, x30, [sp, #-16]!
    0x185378368 <+4>:  mov    x29, sp
    0x18537836c <+8>:  ldr    x8, [x0, #16]
    0x185378370 <+12>: blr    x8
->  0x185378374 <+16>: ldp    x29, x30, [sp], #16
    0x185378378 <+20>: ret  
trdavidson
  • 1,051
  • 12
  • 25
  • You need to provide details about the crash. What is the complete error message? Which line of code causes the crash? – rmaddy Dec 07 '15 at 03:46
  • @rmaddy that's problem, i'm not really sure. It looks like there is some sort of race condition between the server call returning and a new operation being added. Could you point me in the direction of where I should look to provide more useful information? – trdavidson Dec 07 '15 at 04:16
  • The crash log would be the proper place. Or if you are getting the crash while using the debugger, the console will have the error and the stack trace will be shown in the debugger. – rmaddy Dec 07 '15 at 04:18
  • alright, i'm doing my best to reproduce quickly now – trdavidson Dec 07 '15 at 04:20
  • @rmaddy I updated the question with some details, please let know if there is additional information that I should provide/pay attention to. – trdavidson Dec 07 '15 at 04:40
  • It is obvious that the reason for this behavior is because at some point a nil is being inserted to an array... can you please show us the code that is being executed in myOperation ? – Roy K Dec 07 '15 at 05:27
  • @RoyKronenfeld absolutely a nil point is being inserted in an array. The problem is that this doesn't seem to be generated my the executing code inside the myOperation, but rather by the conflict of the server return statement, the addOperation, and then the addOperation in the main thread to update the annotations on the map. – trdavidson Dec 07 '15 at 05:40
  • @rmaddy and Roy, I added some more code to make the flow clearer – trdavidson Dec 07 '15 at 05:53

1 Answers1

0

First of all make sure you initialize that array before inserting any objects into it.

For example, if we are talking about NSMutableArray, then

NSMutableArray *arr = [[NSMutableArray alloc] init];

Secondly, make sure no nil values are being inserted; before insertion make a condition:

if(object) {
    // Insert to array
} else { 
    // Don't insert and investigate why it returns nil if needed
}

By doing that, you will most likely get rid of the crash.

Yet, if it still being reproduced I would suggest to debug it using exception breakpoints and find where the issue specifically comes from, please follow this link for how to do that: Exception Breakpoints

Community
  • 1
  • 1
Roy K
  • 3,319
  • 2
  • 27
  • 43