1

I got -[__NSOrderedSetM removeObjectAtIndex:]: index 0 beyond bounds for empty ordered set in the following code:

- (void)moveAdapter:(SUBaseAdapter *)adapter
               from:(NSMutableOrderedSet *)src
                 to:(NSMutableOrderedSet *)trg {

    SS_ASSERT(adapter);
    SS_ASSERT(src);
    SS_ASSERT(trg);

    dispatch_barrier_sync(self.adaptersQueue, ^{ // CONCURRENT QUEUE

        if (![src containsObject:adapter]) {
            NSString *message = [NSString stringWithFormat:@"moveAdapter: %@ not in src", adapter.providerName];
            [[SULoggerManager sharedInstance] log:message level:SU_LOG_INTERNAL tag:TAG_INTERNAL];
            return;
        }
        if ([trg containsObject:adapter]) {
            NSString *message = [NSString stringWithFormat:@"moveAdapter: %@ already in trg", adapter.providerName];
            [[SULoggerManager sharedInstance] log:message level:SU_LOG_INTERNAL tag:TAG_INTERNAL];
            return;
        }

        [trg addObject:adapter];
        [trg sortUsingDescriptors:@[self.sortDescriptor]];
        [src removeObject:adapter]; //CRASH HERE

    });

}

So, I'm not explicitly calling removeObjectAtIndex:, but maybe removeObject:adapter does?

Here's what I don't understand:

  1. I tried adding anObject to a set, then called removedObject:anObject twice, had no problem.
  2. I thought maybe it's a concurrency issue, where two different threads enter removeObject thinking it's in position 1, and then the second thread fails, but I am using dispatch_barrier_sync, and I don't remove objects from 'src' anywhere else.

Any hints?

Yotam
  • 9,789
  • 13
  • 47
  • 68
  • When you submits a barrier block to adapter queue, a dispatch queue, for synchronous execution. Unlike dispatch_barrier_async, this function does not return until the barrier block has finished. I am wondering, how could you have a concurrency issue as adapter queue will not execute two barrie blocks simulatenously based on my understanding of the barrie block. – ldindu Jul 26 '16 at 09:23
  • I wonder the same about `dispatch_barrier_sync`. Is it possible that you manipulate `src` concurrently outside of this scope? – pronebird Jul 26 '16 at 10:32
  • It doesn't seem feasible that `containsObject:` succeeds and `removeObject:` fails unless the collection is changing outside this method. – Droppy Jul 26 '16 at 10:38

0 Answers0