3 Replies
      Latest reply on Aug 31, 2015 9:40 AM by eskimo
      emafuma Level 1 Level 1 (0 points)

        Hi,

        I'm using a dispatch source as a timer, I noticed that when the object that contains it is deallocated I get a crash:

         

        libdispatch.dylib`_dispatch_xref_dispose:
            0x100134ac8 <+0>:  ldr    w8, [x0, #48]
            0x100134acc <+4>:  cmp    w8, #2
        

         

        This happens only if the dispatch source had been suspended, according to the documentation (https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/GCDWorkQueues/GCDWorkQueues.html)

        You can suspend and resume the delivery of dispatch source events temporarily using the dispatch_suspend and dispatch_resume methods. These methods increment and decrement the suspend count for your dispatch object. As a result, you must balance each call to dispatch_suspend with a matching call to dispatch_resume before event delivery resumes

         

        So I'm wondering if it's not possible to dispatch_source_cancel a suspended dispatch source. Actually the crash is when dealloc ends, the dispatch_source_cancel seems to always work.

         

        Here's my code:

         

        @interface DispatchTimer(){
            dispatch_source_t dispatchSource;
            NSString *uniqueId;
        }
        @end
        @implementation DispatchTimer
        - (void)dealloc {
            NSLog(@"DEALLOCATED DispatchTimer");
           
            if(dispatch_source_testcancel(dispatchSource) == 0){
                dispatch_source_cancel(dispatchSource);
            }
        }
        - (instancetype)init{
            self = [super init];
            if (self) {
                uniqueId = [[NSUUID UUID] UUIDString];
               
                dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
                                                        dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
               
                dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 0);
                uint64_t intervalTime = (int64_t)(1 * NSEC_PER_SEC);
                dispatch_source_set_timer(dispatchSource, startTime, intervalTime, 0);
               
                __weak DispatchTimer *weakSelf = self;
               
                dispatch_source_set_event_handler(dispatchSource, ^{
                    [weakSelf update];
                });
               
                dispatch_resume(dispatchSource);
            }
            return self;
        }
        - (void)stop{
            dispatch_suspend(dispatchSource);
        }
        - (void)update{
            NSLog(@"Update %@", uniqueId);
        }
        

         

        If method 'stop' is called when the DispatchTimer is deallocated I get the crash, if stop is not called everything seems to be fine.

        In the docs they mention dispatch_release but I get an error when using it in ARC.

         

        Thanks for any help.

        • Re: Dispatch Source deallocated
          eskimo Apple Staff Apple Staff (9,090 points)

          I think this is the droid you’re looking for.

          Share and Enjoy

          Quinn "The Eskimo!"
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

          1 of 1 people found this helpful
            • Re: Dispatch Source deallocated
              emafuma Level 1 Level 1 (0 points)

              Thanks for pointing me to that thread.

              So in case of using a dispatch source I will always need to resume it after cancelling ?

                  dispatch_source_cancel(dispatchSource);
                  dispatch_resume(dispatchSource);
              

               

              This seems to work, it's just a little bit counter-intuitive to resume something that is being cancelled at the same time.


              Is there a way to detect if a dispatch source is suspended ?

              According to this there isn't.

              I wonder if there's another way to have a timer that runs my method in a separate thread.

                • Re: Dispatch Source deallocated
                  eskimo Apple Staff Apple Staff (9,090 points)

                  I wonder if there's another way to have a timer that runs my method in a separate thread.

                  There are ways to do that but it’s hard to say whether that’s a good idea or not because you haven’t really discussed the requirements of the DispatchTimer class, you’ve only talked about its internals.

                  Share and Enjoy

                  Quinn "The Eskimo!"
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"