From 0179267bd9b6697599c3999abd30d668feee35ed Mon Sep 17 00:00:00 2001 From: oehhar Date: Thu, 18 Jul 2024 07:48:06 +0000 Subject: Ticket [2d3a81c0] menubutton destroy segfault: proposed solution to preserve also the menu --- generic/tkMenu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/generic/tkMenu.c b/generic/tkMenu.c index 715c6d7..15c8031 100644 --- a/generic/tkMenu.c +++ b/generic/tkMenu.c @@ -1005,6 +1005,11 @@ TkInvokeMenu( goto done; } + /* + * Tk Bug 2d3a81c0: menu may be freed in callback, but menu item is + * preserved. As menu is required to delete menu item later, it segfaults. + */ + Tcl_Preserve(menuPtr); Tcl_Preserve(mePtr); if (mePtr->type == TEAROFF_ENTRY) { Tcl_DString ds; @@ -1062,6 +1067,7 @@ TkInvokeMenu( Tcl_DecrRefCount(commandPtr); } Tcl_Release(mePtr); + Tcl_Release(menuPtr); done: return result; -- cgit v0.12 From f5a920f34101212852f51a1e9ed9fa88ca4dd9f2 Mon Sep 17 00:00:00 2001 From: oehhar Date: Thu, 18 Jul 2024 08:07:50 +0000 Subject: Ticket [2d3a81c0] menubutton destroy segfault: preserve menu pointer in tkWinMenu.c, not in tkMenu.c, as for MacOS. --- generic/tkMenu.c | 11 ++++------- win/tkWinMenu.c | 6 ++++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/generic/tkMenu.c b/generic/tkMenu.c index 15c8031..9ba5a15 100644 --- a/generic/tkMenu.c +++ b/generic/tkMenu.c @@ -982,7 +982,7 @@ MenuWidgetObjCmd( * * Side effects: * Commands may get excecuted; variables may get set; sub-menus may get - * posted. + * posted, the passed menu may be destroyed. * *---------------------------------------------------------------------- */ @@ -991,6 +991,9 @@ int TkInvokeMenu( Tcl_Interp *interp, /* The interp that the menu lives in. */ TkMenu *menuPtr, /* The menu we are invoking. */ + /* Must be protected by Tcl_preserve + * against freeing by the caller + */ int index) /* The zero based index of the item we are * invoking. */ { @@ -1005,11 +1008,6 @@ TkInvokeMenu( goto done; } - /* - * Tk Bug 2d3a81c0: menu may be freed in callback, but menu item is - * preserved. As menu is required to delete menu item later, it segfaults. - */ - Tcl_Preserve(menuPtr); Tcl_Preserve(mePtr); if (mePtr->type == TEAROFF_ENTRY) { Tcl_DString ds; @@ -1067,7 +1065,6 @@ TkInvokeMenu( Tcl_DecrRefCount(commandPtr); } Tcl_Release(mePtr); - Tcl_Release(menuPtr); done: return result; diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index a07765a..9d9e19c 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -1240,11 +1240,17 @@ TkWinHandleMenuEvent( interp = menuPtr->interp; Tcl_Preserve(interp); + /* + * Tk Bug 2d3a81c0: menu may be freed in callback, but menu item is + * preserved. As menu is required to delete menu item later, it segfaults. + */ + Tcl_Preserve(menuPtr); code = TkInvokeMenu(interp, menuPtr, mePtr->index); if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) { Tcl_AddErrorInfo(interp, "\n (menu invoke)"); Tcl_BackgroundException(interp, code); } + Tcl_Release(menuPtr); Tcl_Release(interp); *plResult = 0; returnResult = 1; -- cgit v0.12 From f18f82b3a73261b2d71dc4ee5c7c19ec87546fc1 Mon Sep 17 00:00:00 2001 From: oehhar Date: Thu, 18 Jul 2024 08:11:17 +0000 Subject: Comments changed --- generic/tkMenu.c | 5 +++-- win/tkWinMenu.c | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/generic/tkMenu.c b/generic/tkMenu.c index 9ba5a15..fcf49a6 100644 --- a/generic/tkMenu.c +++ b/generic/tkMenu.c @@ -991,8 +991,9 @@ int TkInvokeMenu( Tcl_Interp *interp, /* The interp that the menu lives in. */ TkMenu *menuPtr, /* The menu we are invoking. */ - /* Must be protected by Tcl_preserve - * against freeing by the caller + /* Must be protected by Tcl_Preserve + * against freeing by the caller. + * Tk Bug [2d3a81c0]. */ int index) /* The zero based index of the item we are * invoking. */ diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index 9d9e19c..cd7c4aa 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -1240,10 +1240,6 @@ TkWinHandleMenuEvent( interp = menuPtr->interp; Tcl_Preserve(interp); - /* - * Tk Bug 2d3a81c0: menu may be freed in callback, but menu item is - * preserved. As menu is required to delete menu item later, it segfaults. - */ Tcl_Preserve(menuPtr); code = TkInvokeMenu(interp, menuPtr, mePtr->index); if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) { -- cgit v0.12