2

Consider the following code:

@interface ViewController ()
@property (nonatomic, strong) dispatch_source_t source;
@end

@implementation ViewController

-(void)viewDidLoad {
    [super viewDidLoad];

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_resume(self.source);
    dispatch_source_set_timer(self.source, dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), 0.2 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(self.source, ^{
        NSLog(@"%s",__func__);
    });
}

@end

If I use dispatch_source_create to create the same DISPATCH_SOURCE_TYPE_TIMER twice, the app will crash. Why?

Is there any difference between creating a dispatch source once and twice like in above example?

libdispatch.dylib`_dispatch_xref_dispose:
    0x10015e174 <+0>:  ldr    w8, [x0, #48]
    0x10015e178 <+4>:  cmp    w8, #2                    ; =2 
    0x10015e17c <+8>:  b.hs   0x10015e184               ; <+16>
    0x10015e180 <+12>: ret    
    0x10015e184 <+16>: stp    x20, x21, [sp, #-16]!
    0x10015e188 <+20>: adrp   x20, 41
    0x10015e18c <+24>: add    x20, x20, #3849           ; =3849 
    0x10015e190 <+28>: adrp   x21, 46
    0x10015e194 <+32>: add    x21, x21, #2440           ; =2440 
    0x10015e198 <+36>: str    x20, [x21]
    0x10015e19c <+40>: ldp    x20, x21, [sp], #16
->  0x10015e1a0 <+44>: brk    #0x1
JWWalker
  • 22,385
  • 6
  • 55
  • 76
Jimmy
  • 55
  • 4
  • Why are you doing that? The first one will just be deallocated anyway when you assign the second to the same property, – Paulw11 Aug 25 '16 at 10:33
  • @Paulw11 I know it is meaningless code like this .the first will be deallocated when assign second .but then I resume the second one .there is no way will crash ,and I thought it will still work fine but it did !how ? – Jimmy Aug 25 '16 at 10:37
  • It looks like a timing issue as the crash is happening in the disposal of the dispatch object. – Paulw11 Aug 25 '16 at 10:46

1 Answers1

5

As they say, a picture is worth a thousand words:

detailed info

Basically you're releasing a suspended dispatch object, which seems to be prohibited by CGD.

Resuming the first timer will make the crash go away:

self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_resume(self.source);
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_resume(self.source);
Community
  • 1
  • 1
Cristik
  • 30,989
  • 25
  • 91
  • 127