1

Could somebody, please, explain me why I get error EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) in dispatch_semaphore_wait in the following code:

-(void) initialize {
  dispatch_queue_t queue = dispatch_queue_create("My queue", NULL);
  dispatch_semaphore_t sem = dispatch_semaphore_create(1);
  self.queue = queue;
  self.sem = sem;
  self.myarray = [[NSMutableArray alloc]init];
  [self.myarray addObject: [[MyObject alloc] init]];
}
-(MyObject *) method1 {
  //do something
  dispatch_semaphore_wait(self.sem, DISPATCH_TIME_FOREVER);
  MyObject *obj = [self.myarray objectAtIndex:0];
  dispatch_barrier_sync(self.queue, ^{
    [self.myarray removeObjectAtIndex:0];
  });
  return obj;
}

-(void) method2:(MyObject *)object {
  //do something
  dispatch_barrier_async(self.queue, ^{
    [self.myarray addObject:object];
    dispatch_semaphore_signal(self.sem);
  });
}

I found similar question Why does this code cause "EXC_BAD_INSTRUCTION"?, but in my case I am using ARC and I do not write explicitly nowhere dispatch_release(sem);

Community
  • 1
  • 1
zyxel
  • 1,084
  • 3
  • 15
  • 23
  • How is "queue" defined? Clearly the one in -initialize is not the same one. – ahwulf Aug 01 '13 at 13:55
  • the same, i forgot to add code that assigns local variables to the instance variables – zyxel Aug 02 '13 at 07:27
  • So... uh... do you still have the problem now that you've fixed the code? Because if that fixed your code, then you should accept the answer, not edit the question to make it pointless. – ipmcc Aug 03 '13 at 03:27
  • I did not change the code, I edited only some typos and inaccuracy only in text that I posted here. Now the code here is the code that I have in program. So the answer is NO, it did not fix the problem. – zyxel Aug 03 '13 at 15:00
  • @nru Are you sure instance method `initialize` has been invoked at all before you send `method1` and method `method2`? Check if the semaphore and queue ivar is not nil before using it, e.g. `assert(self.sem)`. Also, your code makes not munch sense. Your usage of the semaphore is also not correct, in that it does not prevent to access the array even if it is empty, so you get an exception. – CouchDeveloper Aug 05 '13 at 10:46
  • @CouchDeveloper, sorry I again was inaccurate and forgot to add initialisation code for array here. Hopefully now I have everything in code.`initialize` is always invoked before I send `method1` and `method2`, so semaphore and queue are not nil when I am using them. Also array is initialised and has one element in it at the beginning. In one thread I always call in order method1, method2, method1, method2,... so there is no possibility that in one thread array will be empty. But when another thread want to access method1 it should wait, until first thread will signal in method2. – zyxel Aug 05 '13 at 14:02
  • possible duplicate of [EXC\_BAD\_INSTRUCTION (code=EXC\_I386\_INVOP, subcode=0x0)](http://stackoverflow.com/questions/10734893/exc-bad-instruction-code-exc-i386-invop-subcode-0x0) – Ilmari Karonen Jan 02 '14 at 01:02

3 Answers3

2

The sem you created in your initialize method is locally scoped to that method. It needs to be accessible to the other methods. If you have an iVar named sem that you're attempting to assign, you're shadowing it by declaring a local variable in initialize. (Same thing with queue, by the way.)

Also, you appear to have a typo here, in that you call dispatch_semaphore_wait(sen, DISPATCH_TIME_FOREVER); (i.e. se n vs se m)

ipmcc
  • 29,581
  • 5
  • 84
  • 147
1

You are allowing simultaneous access to the array self.myarray without sufficient protection. You modify the array with -addObject: and -removeObjectAtIndex: on the serial queue self.queue but you read from it using -objectAtIndex: without any protection. That means you may be reading from it at the same time you're writing to it, which is not safe. You need to also put the -objectAtIndex: call on the serial queue.

Also, you are using barrier functions with a serial queue, which doesn't make any sense.

-(MyObject *) method1 {
  //do something
  dispatch_semaphore_wait(self.sem, DISPATCH_TIME_FOREVER);
  __block MyObject *obj;
  dispatch_sync(self.queue, ^{
    obj = [self.myarray objectAtIndex:0];
    [self.myarray removeObjectAtIndex:0];
  });
  return obj;
}

-(void) method2:(MyObject *)object {
  //do something
  dispatch_async(self.queue, ^{
    [self.myarray addObject:object];
    dispatch_semaphore_signal(self.sem);
  });
}
Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
0

This kind of crash will happen when you are running a (vector)extension which is not supported on your CPU.

For example, in xcode 5 under "project-settings / build-settings / Code Generation, set the "Enable Additional Vector extensions" to "AVX2". Build your executable.

Now run it on an:

  • Intel Core i5: it's going to crash (wherever the compiler decided to use avx2) with 'exc_i386_invop subcode=0x0'.
  • Intel Core i7: it will work.
kalmiya
  • 2,988
  • 30
  • 38
  • This doesn't work for me. When I try to call `tableColumn?.identifier` in `tableView:viewForTableColumn:row:` in my Table delegate I get this error – Arc676 Dec 29 '14 at 07:39
  • Try disabling vector extensions ( avx2, sse etc ) and see if at one point it will work. – kalmiya Dec 31 '14 at 16:03
  • Sorry, that was a while ago. I stored by `NSTextField`s in an array and accessed those. Thanks for helping though :) – Arc676 Jan 01 '15 at 09:22