[macos] ensure valid timer before firing (PR #25871)

24 views
Skip to first unread message

Federico Perini

unread,
Oct 9, 2025, 5:13:09 AM (8 days ago) Oct 9
to wx-...@googlegroups.com, Subscribed

Please discard the previous PR.

On macOS, it seems like CFRunLoopTimerInvalidate() doesn't prevent already-queued timer callbacks from firing.
This can cause crashes when a wxTimer() is invoked after Stop() or the destructor has been called, as the timer object may have been destroyed.

This fix adds a validity check using CFRunLoopTimerIsValid() before processing the callback, ensuring we don't dereference invalid timer pointers.

This crash was observed in CodeBlocks IDE on macOS where timer events would occasionally fire after cleanup:

VM Region Info: 0x1 is not in any region.  Bytes before following region: 4363567103
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      __TEXT                      10416c000-104354000    [ 1952K] r-x/r-x SM=COW  /Applications/CodeBlocks.app/Contents/MacOS/codeblocks

Application Specific Information:
abort() called


Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	       0x188452388 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x18848b88c pthread_kill + 296
2   libsystem_c.dylib             	       0x188394a3c abort + 124
3   libwx_baseu-3.2.0.dylib       	       0x1051f06b8 wxFatalSignalHandler(int) + 52 (utilsunx.cpp:1522)
4   libsystem_platform.dylib      	       0x1884c56a4 _sigtramp + 56
5   libwx_osx_cocoau_core-3.2.0.dylib	       0x105bb3498 wxTimerImpl::Notify() + 36 (timer.h:47)
6   libwx_osx_cocoau_core-3.2.0.dylib	       0x105bb2e54 wxProcessTimer(__CFRunLoopTimer*, void*) + 96 (timer.cpp:38)
7   CoreFoundation                	       0x18858fc50 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 32
8   CoreFoundation                	       0x18858f910 __CFRunLoopDoTimer + 980
9   CoreFoundation                	       0x18858f44c __CFRunLoopDoTimers + 332
10  CoreFoundation                	       0x188575858 __CFRunLoopRun + 1848
11  CoreFoundation                	       0x188574a98 CFRunLoopRunSpecific + 572
12  HIToolbox                     	       0x19401727c RunCurrentEventLoopInMode + 324
13  HIToolbox                     	       0x19401a31c ReceiveNextEventCommon + 216
14  HIToolbox                     	       0x1941a5484 _BlockUntilNextEventMatchingListInModeWithFilter + 76
15  AppKit                        	       0x18c499a34 _DPSNextEvent + 684
16  AppKit                        	       0x18ce38940 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 688
17  libwx_osx_cocoau_core-3.2.0.dylib	       0x105c684f8 wxGUIEventLoop::OSXDoRun() + 288 (evtloop.mm:319)
18  libwx_baseu-3.2.0.dylib       	       0x1051cc4b0 wxCFEventLoop::DoRun() + 44 (evtloop_cf.cpp:326)
19  libwx_baseu-3.2.0.dylib       	       0x1050de824 wxEventLoopBase::Run() + 248 (evtloopcmn.cpp:87)
20  libwx_baseu-3.2.0.dylib       	       0x1051f0894 wxAppTraits::RunLoopUntilChildExit(wxExecuteData&, wxEventLoopBase&) + 356 (utilsunx.cpp:1635)
21  libwx_osx_cocoau_core-3.2.0.dylib	       0x105b837cc wxGUIAppTraits::WaitForChild(wxExecuteData&) + 104 (apptraits.cpp:46)
22  libwx_baseu-3.2.0.dylib       	       0x1051edb34 wxExecute(char const* const*, int, wxProcess*, wxExecuteEnv const*) + 6124 (utilsunx.cpp:890)
23  libwx_baseu-3.2.0.dylib       	       0x1051ec090 wxExecute(wxString const&, int, wxProcess*, wxExecuteEnv const*) + 108 (utilsunx.cpp:508)
24  libwx_baseu-3.2.0.dylib       	       0x1051c0584 wxDoExecuteWithCapture(wxString const&, wxArrayString&, wxArrayString*, int, wxExecuteEnv const*) + 104 (utilscmn.cpp:653)
25  libwx_baseu-3.2.0.dylib       	       0x1051c0510 wxExecute(wxString const&, wxArrayString&, int, wxExecuteEnv const*) + 52 (utilscmn.cpp:680)
26  libcodeblocks.dylib           	       0x1073d0f2c cbExpandBackticks(wxString&) + 1164 (globals.cpp:911)
27  libcodeblocks.dylib           	       0x107339af4 CompilerCommandGenerator::SetupLinkerOptions(Compiler*, ProjectBuildTarget*) + 644 (compilercommandgenerator.cpp:1050)
28  libcodeblocks.dylib           	       0x107331748 CompilerCommandGenerator::Init(cbProject*) + 3416 (compilercommandgenerator.cpp:165)
29  libcodeblocks.dylib           	       0x10731ef68 Compiler::GetCommandGenerator(cbProject*) + 68 (compiler.cpp:302)
30  codecompletion.dylib          	       0x121859080 ParseManager::AddCompilerDirs(cbProject*, ParserBase*) + 240 (parsemanager.cpp:1872)
31  codecompletion.dylib          	       0x1218519c0 ParseManager::DoFullParsing(cbProject*, ParserBase*) + 92 (parsemanager.cpp:1101)
32  codecompletion.dylib          	       0x1218515f8 ParseManager::CreateParser(cbProject*) + 260 (parsemanager.cpp:567)
33  codecompletion.dylib          	       0x1217f9260 CodeCompletion::OnWorkspaceChanged(CodeBlocksEvent&) + 124 (codecompletion.cpp:2235)
34  codecompletion.dylib          	       0x121813fd8 cbEventFunctor<CodeCompletion, CodeBlocksEvent>::Call(CodeBlocksEvent&) + 128 (cbfunctor.h:49)
35  libcodeblocks.dylib           	       0x1073f7eec Manager::ProcessEvent(CodeBlocksEvent&) + 244 (manager.cpp:268)
36  libcodeblocks.dylib           	       0x1074282a8 PluginManager::NotifyPlugins(CodeBlocksEvent&) + 32 (pluginmanager.cpp:1628)
37  libcodeblocks.dylib           	       0x1074683fc ProjectManager::WorkspaceChanged() + 140 (projectmanager.cpp:1022)
38  libcodeblocks.dylib           	       0x107469834 ProjectManager::EndLoadingWorkspace() + 1788 (projectmanager.cpp:1201)
39  libcodeblocks.dylib           	       0x107468f38 ProjectManager::LoadWorkspace(wxString const&) + 152 (projectmanager.cpp:586)
40  codeblocks                    	       0x1042355b0 0x10416c000 + 824752
41  codeblocks                    	       0x104221f9c 0x10416c000 + 745372
42  libwx_baseu-3.2.0.dylib       	       0x105092760 wxAppConsoleBase::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)(wxEvent&), wxEvent&) const + 148 (appbase.cpp:678)
43  libwx_baseu-3.2.0.dylib       	       0x10509280c wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const + 160 (appbase.cpp:690)
44  libwx_baseu-3.2.0.dylib       	       0x1051b702c wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) + 252 (event.cpp:1482)
45  libwx_baseu-3.2.0.dylib       	       0x1051b6d80 wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*) + 272 (event.cpp:1087)
46  libwx_baseu-3.2.0.dylib       	       0x1051b9004 wxEvtHandler::TryHereOnly(wxEvent&) + 144 (event.cpp:1679)
47  libwx_baseu-3.2.0.dylib       	       0x1051b8d38 wxEvtHandler::TryBeforeAndHere(wxEvent&) + 72 (event.h:4013)
48  libwx_baseu-3.2.0.dylib       	       0x1051b8d78 wxEvtHandler::ProcessEventLocally(wxEvent&) + 36 (event.cpp:1612)
49  libwx_baseu-3.2.0.dylib       	       0x1051b8bec wxEvtHandler::ProcessEvent(wxEvent&) + 360 (event.cpp:1585)
50  libwx_baseu-3.2.0.dylib       	       0x1051b86dc wxEvtHandler::SafelyProcessEvent(wxEvent&) + 40 (event.cpp:1701)
51  libwx_baseu-3.2.0.dylib       	       0x1051b8638 wxEvtHandler::ProcessPendingEvents() + 1100 (event.cpp:1449)
52  libwx_baseu-3.2.0.dylib       	       0x10509225c wxAppConsoleBase::ProcessPendingEvents() + 240 (appbase.cpp:587)
53  libwx_baseu-3.2.0.dylib       	       0x1051cba84 wxCFEventLoop::CommonModeObserverCallBack(__CFRunLoopObserver*, int) + 88 (evtloop_cf.cpp:95)
54  libwx_baseu-3.2.0.dylib       	       0x1051cba1c wxCFEventLoop::OSXCommonModeObserverCallBack(__CFRunLoopObserver*, int, void*) + 76 (evtloop_cf.cpp:72)
55  CoreFoundation                	       0x188575ed8 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36
56  CoreFoundation                	       0x188575dc0 __CFRunLoopDoObservers + 536
57  CoreFoundation                	       0x188575430 __CFRunLoopRun + 784
58  CoreFoundation                	       0x188574a98 CFRunLoopRunSpecific + 572
59  HIToolbox                     	       0x19401727c RunCurrentEventLoopInMode + 324
60  HIToolbox                     	       0x19401a31c ReceiveNextEventCommon + 216
61  HIToolbox                     	       0x1941a5484 _BlockUntilNextEventMatchingListInModeWithFilter + 76
62  AppKit                        	       0x18c499a34 _DPSNextEvent + 684
63  AppKit                        	       0x18ce38940 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 688
64  AppKit                        	       0x18c48cbe4 -[NSApplication run] + 480
65  libwx_osx_cocoau_core-3.2.0.dylib	       0x105c68478 wxGUIEventLoop::OSXDoRun() + 160 (evtloop.mm:301)
66  libwx_baseu-3.2.0.dylib       	       0x1051cc4b0 wxCFEventLoop::DoRun() + 44 (evtloop_cf.cpp:326)
67  libwx_baseu-3.2.0.dylib       	       0x1050de824 wxEventLoopBase::Run() + 248 (evtloopcmn.cpp:87)
68  libwx_baseu-3.2.0.dylib       	       0x105091400 wxAppConsoleBase::MainLoop() + 168 (appbase.cpp:395)
69  libwx_baseu-3.2.0.dylib       	       0x105090f10 wxAppConsoleBase::OnRun() + 32 (appbase.cpp:317)
70  libwx_osx_cocoau_core-3.2.0.dylib	       0x105888160 wxAppBase::OnRun() + 64 (appcmn.cpp:334)
71  libwx_osx_cocoau_core-3.2.0.dylib	       0x105be36dc wxApp::OnRun() + 40 (app.cpp:364)
72  codeblocks                    	       0x104174414 0x10416c000 + 33812
73  libwx_baseu-3.2.0.dylib       	       0x10511d638 wxEntry(int&, wchar_t**) + 304 (init.cpp:497)
74  libwx_baseu-3.2.0.dylib       	       0x10511d7f8 wxEntry(int&, char**) + 56 (init.cpp:509)
75  codeblocks                    	       0x10416cbe0 0x10416c000 + 3040
76  dyld                          	       0x1880eab98 start + 6076

You can view, comment on, or merge this pull request online at:

  https://github.com/wxWidgets/wxWidgets/pull/25871

Commit Summary

  • b92471b [macos] ensure valid timer before firing

File Changes

(1 file)

Patch Links:


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/25871@github.com>

VZ

unread,
Oct 9, 2025, 5:28:14 AM (8 days ago) Oct 9
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#25871)

Thanks for the PR and explanations!

This looks correct to me and not so different from what I had to do in wxTimerWndProc in wxMSW (except I had to use my own container of valid timers as Win32 doesn't have any equivalent of CFRunLoopTimerIsValid()).

@csomor Do you have any objections/comments? If not, I'll merge this soon (and backport to 3.2).


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/25871/c3384974003@github.com>

Stefan Csomor

unread,
Oct 10, 2025, 3:25:10 AM (7 days ago) Oct 10
to wx-...@googlegroups.com, Subscribed

@csomor approved this pull request.

Perfect, I didn't know that, thanks a lot!


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/25871/review/3321708819@github.com>

VZ

unread,
Oct 10, 2025, 4:06:23 AM (7 days ago) Oct 10
to wx-...@googlegroups.com, Subscribed

Closed #25871 via f25aec1.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/25871/issue_event/20201122121@github.com>

Reply all
Reply to author
Forward
0 new messages