Ticket UUID: | fc5073a451c4cc95d0bebe963d9c440ab3b31481 | |||
Title: | macOS Aqua : Tk crash | |||
Type: | Bug | Version: | trunk | |
Submitter: | nab | Created on: | 2022-02-04 12:38:37 | |
Subsystem: | 11. Aqua Menus | Assigned To: | nobody | |
Priority: | 5 Medium | Severity: | Minor | |
Status: | Closed | Last Modified: | 2023-07-03 02:57:19 | |
Resolution: | Fixed | Closed By: | chrstphrchvz | |
Closed on: | 2023-07-03 02:57:19 | |||
Description: |
Hi Marc, please consider attached script. it involves baltip (a tooltip extension) but it's the easiest way to trigger it: https://github.com/aplsimple/baltip nothing urgent as Wish does not crash when filedialog proc is not coming from a bind... so to trigger the crash: -launch the script -put the mouse over the 'Browse' button -while 'Import file' tool tip is displayed click on the 'Browse' button -on the FileDialog window click on 'options' buttons in order to display file filters -click on the file filter menubutton in order to display available filters and wait ++ | |||
User Comments: |
chrstphrchvz added on 2023-07-03 02:57:19:
In response to Marc’s comment dated 2022-02-07 14:08:13: my comment on [bb7f5785a5] dated 2023-07-03 02:11:40 tries to explain the crashes in these tickets as well as a more general problem which may still exist. chrstphrchvz added on 2022-04-10 19:24:10: The fix for this issue appears to also resolve another error I’ve encountered (and seen other reports of): objc[19074]: Invalid or prematurely-freed autorelease pool 0x7f8c0789dd40. One trigger for this other error is to destroy the root window immediately after loading Tk but before entering any idle event loops, as done by some Tcl::pTk tests, but also by this example: package require Tk after idle {destroy .} For the examples I tried, I notice that the idle task gets handled during generateExposeEvents:. kevin_walzer added on 2022-02-12 16:31:31: As this fix has been tested with no apparent regressions, I have committed it to core-8-6-branch and trunk. nab added on 2022-02-09 09:27:30: after more digging it appears that my winfo exists issue is due to baltip... so I'm good with Kevin's fix ++ chrstphrchvz added on 2022-02-09 00:27:45: Using core-8-6-branch, I do not observe the autorelease corruption issue once the proposed fix is applied. The use-after-free I mentioned seems to occur for any file selection dialog, so I opened a separate issue: [88cfdcb304] nab added on 2022-02-08 15:51:13: so, after 2 days of testing mac_styles_87 branch with Kevin fix I only saw one weird thing. winfo exists have reported that a toplevel exists but it wasn't displayed. I use to create toplevel with withdraw/deiconify sequence. I need more time though in order to see if it happens again with/without the fix. but provided script does not crash anymore. thanks, ++ kevin_walzer added on 2022-02-07 14:31:51: The crash does not occur if the window is destroyed after the menu posts, only before. My theory is that the presence of the menu may cause the re-set of the autorelease pool to be premature - the menu may be trying to access memory that has been released. I don't know of any additional tests that can be conducted other than the test suite, which passed with no issues. marc_culler (claiming to be Marc Culler) added on 2022-02-07 14:08:13: Indeed, this must be tested very, very thoroughly. This is definitely the sort of thin ice situation where one fix can cause many breakages. The purpose of _resetAutoreleasePool method is to replicate an undocumented component of Apple's event loop which Tk must replace in order to work. Apple does say that aach cycle of Apple's event loop creates a new outermost autorelease pool, but they provide no details. The main call to that function in Tk occurs in TkMacOSXNotify.c and that one seems more or less comparable to what Apple describes. It is possible that calling that method when a window is destroyed is wrong. There are definitely situations when the method must not be called and some work is done to prevent those (nested) calls which are known to lead to crashes. (Please read the discussion in macOS/README.) I am not able to provide an explanation for why it was being called in TkDeadWindow, so that may have been a workaround which was wrong at the time it was added. But I would feel much better about the change if someone could provide an explanation for why it leads to a crash in this situation. kevin_walzer added on 2022-02-07 03:08:24: I have committed a possible fix for this crash in the autorelease_pool_corrupted branch. The fix is simple - I am disabling a re-set of an autorelease pool. The crash error suggests memory corruption. I believe this code was put in place by Marc and I'm not sure of all of its use cases - please test carefully and see if you discover any side effects. The test suite passes without issue with this fix. nab added on 2022-02-05 17:01:29: @Kevin, the crash seems to occur when destroying a toplevel while a menu is posted. In the attached script baltip (a great extension by the way which provide method to hide a displayed tip (that's what I use in real life...)) is destroying its toplevel after a certain amount of time (-per10 1000 option) and it seems that's the cause of crash. for example you'll find attached another script without baltip and which trigger the same crash ++ kevin_walzer added on 2022-02-05 15:00:11: As an additional note, I am unable to reproduce the crash using the tooltip package from Tklib. kevin_walzer added on 2022-02-05 14:45:31: I see the crash. I suspect it's caused somehow by the integration between the tooltip window and the native file dialog - something may be overloading Tk there. But my initial question is why isn't the tooltip window being destroyed when the "Browse" button is pushed - that's terrible UI design. The design of that baltip package doesn't provide an easy way to get at the actual tooltip window to configure it to be destroyed via a <Button-1> event, so this is difficult to address at the script level. But while I also understand crashes should not happen, crashes that are triggered by bad behavior from an extension package are not necessarily a priority for core maintainers. Have you filed a bug with the baltip maintainer? nab added on 2022-02-05 11:23:42: Hi Christopher, here's mine: Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: Namespace OBJC, Code 1 Application Specific Information: autorelease pool page 0x7fb69c03e000 corrupted magic 0x00000000 0x00000000 0x00000000 0x00000000 should be 0xa1a1a1a1 0x4f545541 0x454c4552 0x21455341 pthread 0x10782d600 should be 0x10782d600 Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_kernel.dylib 0x7ff81ade4dfe __abort_with_payload + 10 1 libsystem_kernel.dylib 0x7ff81ade6893 abort_with_payload_wrapper_internal + 80 2 libsystem_kernel.dylib 0x7ff81ade6843 abort_with_reason + 19 3 libobjc.A.dylib 0x7ff81acb2bce _objc_fatalv(unsigned long long, unsigned long long, char const*, __va_list_tag*) + 114 4 libobjc.A.dylib 0x7ff81acb2b5c _objc_fatal(char const*, ...) + 135 5 libobjc.A.dylib 0x7ff81acb1fe6 void AutoreleasePoolPage::busted<void (*)(char const*, ...)>(void (*)(char const*, ...)) const + 120 6 libobjc.A.dylib 0x7ff81acb38a1 AutoreleasePoolPage::busted_die() const + 9 7 libobjc.A.dylib 0x7ff81ac960e8 objc_autoreleasePoolPop + 41 8 CoreFoundation 0x7ff81ae8702c _CFAutoreleasePoolPop + 22 9 Foundation 0x7ff81bd4bb29 __NSThreadPerformPerform + 217 10 CoreFoundation 0x7ff81aec58fd __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 11 CoreFoundation 0x7ff81aec5865 __CFRunLoopDoSource0 + 180 12 CoreFoundation 0x7ff81aec55e4 __CFRunLoopDoSources0 + 242 13 CoreFoundation 0x7ff81aec401b __CFRunLoopRun + 893 14 CoreFoundation 0x7ff81aec35dd CFRunLoopRunSpecific + 563 15 HIToolbox 0x7ff823b004f1 RunCurrentEventLoopInMode + 292 16 HIToolbox 0x7ff823b00247 ReceiveNextEventCommon + 587 17 HIToolbox 0x7ff823afffe5 _BlockUntilNextEventMatchingListInModeWithFilter + 70 18 AppKit 0x7ff81d8f2d88 _DPSNextEvent + 886 19 AppKit 0x7ff81d8f13f4 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1411 20 AppKit 0x7ff81e04a747 _NSHLTBMenuEventProc + 213 21 HIToolbox 0x7ff823b66add IsUserStillTracking(MenuSelectData*, unsigned char*) + 198 22 HIToolbox 0x7ff823c844aa TrackMenuCommon(MenuSelectData&, unsigned char*, SelectionData*, MenuResult*, MenuResult*) + 1605 23 HIToolbox 0x7ff823c8089a PopUpMenuSelectCore(MenuData*, Point, double, Point, unsigned short, unsigned int, unsigned int, Rect const*, unsigned short, unsigned int, Rect const*, Rect const*, __CFDictionary const*, __CFString const*, OpaqueMenuRef**, unsigned short*) + 1932 24 HIToolbox 0x7ff823c7fc2c _HandlePopUpMenuSelection8(OpaqueMenuRef*, OpaqueEventRef*, unsigned int, Point, unsigned short, unsigned int, unsigned int, Rect const*, unsigned short, Rect const*, Rect const*, __CFDictionary const*, __CFString const*, OpaqueMenuRef**, unsigned short*) + 410 25 HIToolbox 0x7ff823b53f19 _HandlePopUpMenuSelectionWithDictionary + 329 26 AppKit 0x7ff81dd8b874 SLMPerformPopUpCarbonMenu + 2232 27 AppKit 0x7ff81dc30c81 _NSSLMPopUpCarbonMenu3 + 1125 28 AppKit 0x7ff81dc30776 -[NSCarbonMenuImpl popUpMenu:atLocation:width:forView:withSelectedItem:withFont:withFlags:withOptions:] + 462 29 AppKit 0x7ff81dc651b2 -[NSPopUpButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 562 30 AppKit 0x7ff81daf2f78 -[NSControl mouseDown:] + 678 31 AppKit 0x7ff81daf1457 -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 4949 32 AppKit 0x7ff81da65390 -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 2582 33 AppKit 0x7ff81da6475a -[NSWindow(NSEventRouting) sendEvent:] + 352 34 AppKit 0x7ff81da62b28 -[NSApplication(NSEvent) sendEvent:] + 352 35 Tk 0x103186d9d -[TKApplication(TKNotify) sendEvent:] + 125 (tkMacOSXNotify.c:207) 36 AppKit 0x7ff81dba51df -[NSApplication _doModalLoop:peek:] + 364 37 AppKit 0x7ff81dba3cc3 __35-[NSApplication runModalForWindow:]_block_invoke_2 + 64 38 AppKit 0x7ff81dba3c70 __35-[NSApplication runModalForWindow:]_block_invoke + 78 39 AppKit 0x7ff81dba3512 _NSTryRunModal + 100 40 AppKit 0x7ff81dba33f9 -[NSApplication runModalForWindow:] + 128 41 AppKit 0x7ff81e303429 -[NSSavePanel runModal] + 451 42 Tk 0x103172b29 showOpenSavePanel + 409 (tkMacOSXDialog.c:378) 43 Tk 0x10317229a Tk_GetOpenFileObjCmd + 2074 (tkMacOSXDialog.c:852) 44 Tcl 0x1032b13a4 0x10328f000 + 140196 45 Tcl 0x1032ad4eb Tcl_EvalObjv + 363 46 Tcl 0x1032aed8d 0x10328f000 + 130445 47 Tcl 0x1032ae29a Tcl_EvalEx + 26 48 Tk 0x1030aac73 Tk_BindEvent + 3059 (tkBind.c:2631) 49 Tk 0x1030b308f TkBindEventProc + 383 (tkCmds.c:319) 50 Tk 0x1030bab58 Tk_HandleEvent + 456 (tkEvent.c:1307) 51 Tk 0x1030bb500 WindowEventProc + 96 (tkEvent.c:1738) 52 Tcl 0x1033712cc Tcl_ServiceEvent + 156 53 Tcl 0x1033715c8 Tcl_DoOneEvent + 376 54 Tk 0x1030bb9db Tk_MainLoop + 43 (tkEvent.c:2124) 55 Tk 0x1030c9b52 Tk_MainEx + 1218 (tkMain.c:377) 56 Wish 0x102da1de9 main + 73 (tkAppInit.c:96) 57 dyld 0x1077b24fe start + 462 so yes, it seems to be the same I've seen many autorelease pool corruption issue with Tk8.7 on macOS and I've adressed many of them by after 1 [list ...] but not this one :) ++ chrstphrchvz added on 2022-02-05 06:03:35: From looking online for any similar issues, I notice an autorelease pool corruption issue seen in gitk in the past year. Users and downstream packagers have not figured out a cause or actual fix for it (there is a workaround of changing/removing a configuration file). I don’t know if it’s related to this ticket, but it could probably use Tk Aqua developers’ help investigating: https://stackoverflow.com/q/65938739, https://github.com/Homebrew/discussions/discussions/705 chrstphrchvz added on 2022-02-05 06:01:20: I may have reproduced the issue; does this error and backtrace match what Nicolas sees? objc[7822]: autorelease pool page 0x6250005a6000 corrupted magic 0x5a800219 0x00000000 0x00000000 0x00000000 should be 0xa1a1a1a1 0x4f545541 0x454c4552 0x21455341 pthread 0x100094600 should be 0x100094600 This is likely not an area of Tk Aqua I’m familiar with enough to suggest a fix for. Something strange I notice is that when LLDB is attached to Tk, once the crash happens, the keyboard stops working in other programs until I force quit the LLDB process. I wonder if there is a special environment variable or similar to help debug the Objective-C runtime abort. I do not always get a crash after clicking the filter menubutton, but AddressSanitizer (-fsanitize=address -DPURIFY) does report a use-after-free if I dismiss the dialog: ================================================================= ==7704==ERROR: AddressSanitizer: heap-use-after-free on address 0x60300037d3e8 at pc 0x0001020edb72 bp 0x7ff7bfefa690 sp 0x7ff7bfefa688 READ of size 8 at 0x60300037d3e8 thread T0 #0 0x1020edb71 in showOpenSavePanel tkMacOSXDialog.c:390 #1 0x1020ea774 in Tk_GetOpenFileObjCmd tkMacOSXDialog.c:852 #2 0x1043aed21 in Dispatch tclBasic.c:4468 #3 0x10438f85e in TclNRRunCallbacks tclBasic.c:4504 #4 0x10438dbdb in Tcl_EvalObjv tclBasic.c:4226 #5 0x10439b1d3 in TclEvalEx tclBasic.c:5373 #6 0x104394699 in Tcl_EvalEx tclBasic.c:5038 #7 0x10162fdc3 in Tk_BindEvent tkBind.c:2602 #8 0x10169066b in TkBindEventProc tkCmds.c:319 #9 0x101700334 in Tk_HandleEvent tkEvent.c:1292 #10 0x101707cc0 in WindowEventProc tkEvent.c:1723 #11 0x104ff8fe8 in Tcl_ServiceEvent tclNotify.c:670 #12 0x104ffbb21 in Tcl_DoOneEvent tclNotify.c:967 #13 0x10170b8af in Tk_MainLoop tkEvent.c:2109 #14 0x1017da5e4 in Tk_MainEx tkMain.c:377 #15 0x100006c5e in main tkAppInit.c:93 #16 0x1000194fd in start+0x1cd (dyld:x86_64+0x54fd) 0x60300037d3e8 is located 8 bytes inside of 24-byte region [0x60300037d3e0,0x60300037d3f8) freed by thread T0 here: #0 0x10051f829 in wrap_free+0xa9 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x47829) #1 0x104325cc4 in TclpFree tclAlloc.c:722 #2 0x104405324 in Tcl_Free tclCkalloc.c:1226 #3 0x1020e297e in -[TKApplication(TKDialog) tkFilePanelDidEnd:returnCode:contextInfo:] tkMacOSXDialog.c:261 #4 0x1020ed97b in showOpenSavePanel tkMacOSXDialog.c:379 #5 0x1020ea774 in Tk_GetOpenFileObjCmd tkMacOSXDialog.c:852 #6 0x1043aed21 in Dispatch tclBasic.c:4468 #7 0x10438f85e in TclNRRunCallbacks tclBasic.c:4504 #8 0x10438dbdb in Tcl_EvalObjv tclBasic.c:4226 #9 0x10439b1d3 in TclEvalEx tclBasic.c:5373 #10 0x104394699 in Tcl_EvalEx tclBasic.c:5038 #11 0x10162fdc3 in Tk_BindEvent tkBind.c:2602 #12 0x10169066b in TkBindEventProc tkCmds.c:319 #13 0x101700334 in Tk_HandleEvent tkEvent.c:1292 #14 0x101707cc0 in WindowEventProc tkEvent.c:1723 #15 0x104ff8fe8 in Tcl_ServiceEvent tclNotify.c:670 #16 0x104ffbb21 in Tcl_DoOneEvent tclNotify.c:967 #17 0x10170b8af in Tk_MainLoop tkEvent.c:2109 #18 0x1017da5e4 in Tk_MainEx tkMain.c:377 #19 0x100006c5e in main tkAppInit.c:93 #20 0x1000194fd in start+0x1cd (dyld:x86_64+0x54fd) previously allocated by thread T0 here: #0 0x10051f6e0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x476e0) #1 0x104325ca4 in TclpAlloc tclAlloc.c:699 #2 0x104404fd2 in Tcl_Alloc tclCkalloc.c:1059 #3 0x1020ea27a in Tk_GetOpenFileObjCmd tkMacOSXDialog.c:836 #4 0x1043aed21 in Dispatch tclBasic.c:4468 #5 0x10438f85e in TclNRRunCallbacks tclBasic.c:4504 #6 0x10438dbdb in Tcl_EvalObjv tclBasic.c:4226 #7 0x10439b1d3 in TclEvalEx tclBasic.c:5373 #8 0x104394699 in Tcl_EvalEx tclBasic.c:5038 #9 0x10162fdc3 in Tk_BindEvent tkBind.c:2602 #10 0x10169066b in TkBindEventProc tkCmds.c:319 #11 0x101700334 in Tk_HandleEvent tkEvent.c:1292 #12 0x101707cc0 in WindowEventProc tkEvent.c:1723 #13 0x104ff8fe8 in Tcl_ServiceEvent tclNotify.c:670 #14 0x104ffbb21 in Tcl_DoOneEvent tclNotify.c:967 #15 0x10170b8af in Tk_MainLoop tkEvent.c:2109 #16 0x1017da5e4 in Tk_MainEx tkMain.c:377 #17 0x100006c5e in main tkAppInit.c:93 #18 0x1000194fd in start+0x1cd (dyld:x86_64+0x54fd) |
