From d6f66237b021b4acd6652c34704fc93134689b65 Mon Sep 17 00:00:00 2001 From: Nick Bourdakos Date: Tue, 4 Apr 2023 07:46:06 -0700 Subject: [PATCH] Update Apple implementation to cancel the timer before calling the callback This fixes a crash where the Timer is destroyed as soon as the callback is called, so Timer::Stop can't be safely called. PiperOrigin-RevId: 521760888 --- internal/platform/implementation/apple/timer.mm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/internal/platform/implementation/apple/timer.mm b/internal/platform/implementation/apple/timer.mm index 7ea292e7..36ac8e9c 100644 --- a/internal/platform/implementation/apple/timer.mm +++ b/internal/platform/implementation/apple/timer.mm @@ -52,13 +52,17 @@ bool Timer::Create(int delay, int interval, absl::AnyInvocable callback) dispatch_get_main_queue()); dispatch_source_set_event_handler(timer_, ^{ + // If our interval is `DISPATCH_TIME_FOREVER`, it means we only want the timer to fire once. + // We need to cancel the timer before the callback is called since the `Timer` object may no + // longer exist immediately after invoking the callback. + if (intervalInNanoseconds == DISPATCH_TIME_FOREVER && timer_ != nil) { + dispatch_source_cancel(timer_); + timer_ = nil; + } + if (callback_ != nil) { callback_(); } - // If our interval is `DISPATCH_TIME_FOREVER`, it means we only want the timer to fire once. - if (intervalInNanoseconds == DISPATCH_TIME_FOREVER) { - Stop(); - } }); dispatch_source_set_timer(timer_, dispatch_time(DISPATCH_TIME_NOW, delayInNanoseconds),