9 out of 10 programmers couldn't cause this crash if they tried: Timer::TimerThread::callTimers - Pure Virtual Function call

Anyone know how we’ve managed to get a crash on a pure virtual function call? Some kind of construction order problem maybe? Calling startTimer from a background thread?

I’m sure I once figured out how to do it but I’ve forgotten since! Any pointers appreciated.

+                           6831 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__  (in CoreFoundation) + 17  [0x7fff38878d52]
+                             6831 juce::MessageQueue::runLoopSourceCallback(void*)  (in App) + 129  [0x1044967c1]
+                               6831 juce::Timer::TimerThread::callTimers()  (in App) + 233  [0x104495ca9]
+                                 6831 __cxa_pure_virtual  (in libc++abi.dylib) + 18  [0x7fff6fc15e92]

Maybe it’s deleting the object on a background thread. I can see that might do it.

Is there a possibility that the Timer object is being destroyed on a background thread while the timer callback is being called on the message thread?

We do delete some objects on background threads to avoid long hangs waiting for network threads to terminate. So this is a definite possibility. I’m trying to think about the destruction order here. At what point do my virtual function calls to timerCallback become fubar … before ~Timer() is called?

I think there may be brief window during destruction where the derived part of the object which implements timerCallback has been destroyed (and the vtable pointer has been adjusted to point to Timer’s vtable), but the Timer base is still alive and running. If a timer callback is processed at this point, we’ll end up looking up timerCallback in Timer’s vtable, and we’ll try to call an unimplemented pure virtual function.

It’s normally a good idea to call stopTimer in the destructors of any classes derived from Timer to avoid issues like these.

4 Likes

Yeah, I think this seems like a reasonable thing. Might be good if ~Timer() asserted if it was still running and called on the non-message thread :slight_smile:

It’s so hard to reproduce though I think it’ll be months before we know if it’s fixed.

I’ve added in the assertion you suggested:

2 Likes

Great! Look forward to hitting it :slight_smile: