Assertion failure during deinit due to... DispatchSourceTimer?

I have

var idleScanTimer = DispatchSource.makeTimerSource()

as a class ivar. When the object is started, I have

self.idleScanTimer.schedule(deadline: .now(), repeating: Double(5.0*60))

(and it sets an event handler, that checks some times.)

When the object is stopped, it calls self.idleScanTimer.cancel().

At some point, the object containing it is deallocated, and ... sometimes, I think, not always, it crashes:

Crashed Thread:        61  Dispatch queue: NEFlow queue
[...]
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: Release of an inactive object
[...]
Thread 61 Crashed::  Dispatch queue: NEFlow queue
0   libdispatch.dylib             	    0x7ff81c1232cd _dispatch_queue_xref_dispose.cold.2 + 24
1   libdispatch.dylib             	    0x7ff81c0f84f6 _dispatch_queue_xref_dispose + 55
2   libdispatch.dylib             	    0x7ff81c0f2dec -[OS_dispatch_source _xref_dispose] + 17
3   com.kithrup.simpleprovider	       0x101df5fa7 MyClass.deinit + 87
4   com.kithrup.simpleprovider	       0x101dfbdbb MyClass.__deallocating_deinit + 11
5   libswiftCore.dylib            	    0x7ff829a63460 _swift_release_dealloc + 16
6   com.kithrup.simpleprovider	       0x101e122f4 0x101de7000 + 176884
7   libswiftCore.dylib            	    0x7ff829a63460 _swift_release_dealloc + 16
8   libsystem_blocks.dylib        	    0x7ff81bfdc654 _Block_release + 130
9   libsystem_blocks.dylib        	    0x7ff81bfdc654 _Block_release + 130
10  libdispatch.dylib             	    0x7ff81c0f3317 _dispatch_client_callout + 8
11  libdispatch.dylib             	    0x7ff81c0f9317 _dispatch_lane_serial_drain + 672
12  libdispatch.dylib             	    0x7ff81c0f9dfd _dispatch_lane_invoke + 366
13  libdispatch.dylib             	    0x7ff81c103eee _dispatch_workloop_worker_thread + 753
14  libsystem_pthread.dylib       	    0x7ff81c2a7fd0 _pthread_wqthread + 326
15  libsystem_pthread.dylib       	    0x7ff81c2a6f57 start_wqthread + 15

I tried changing it to an optional and having the deinit call .cancel() and set it to nil, but it still crashes.

I can't figure out how to get it deallocated in a small, standalone test program.

Answered by DTS Engineer in 794563022

This crash means that you’ve released a suspended source. Most folks never suspend and resume sources, so the most common cause is releasing a source without ever resuming it. For example, this code will crash as you’ve described:

import Dispatch

func main() {
    autoreleasepool {
        let source = DispatchSource.makeTimerSource()
        print(source)
    }
}

main()

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

BTW: the forum software things that the abort cause number is "sensitive language," and it's taken me about 20 minutes to figure tha tout.

Oh, hm. Ok, that's not it. It's when my object is deinit'ted at all. That seems very weird.

This crash means that you’ve released a suspended source. Most folks never suspend and resume sources, so the most common cause is releasing a source without ever resuming it. For example, this code will crash as you’ve described:

import Dispatch

func main() {
    autoreleasepool {
        let source = DispatchSource.makeTimerSource()
        print(source)
    }
}

main()

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Fortunately that case didn't come into play -- I only .activate() and .cancel() it. The documentation wasn't really clear, but I assume a cancelled source can be released.

Also, as I said, that didn't appear to be my real problem, so I'm not sure what all was going on. I've rewritten the code that uses kevent into ObjC, to see if that helps (ie., I got very confused about conversions again).

Assertion failure during deinit due to... DispatchSourceTimer?
 
 
Q