Adapted from https://core.tcl-lang.org/tk/info/b1876b9ebc4b Index: generic/tkInt.h ================================================================== --- a/generic/tkInt.h.orig +++ b/generic/tkInt.h @@ -1094,10 +1094,11 @@ /* * Themed widget set init function: */ MODULE_SCOPE int Ttk_Init(Tcl_Interp *interp); +MODULE_SCOPE void Ttk_TkDestroyedHandler(Tcl_Interp *interp); /* * Internal functions shared among Tk modules but not exported to the outside * world: */ Index: generic/tkWindow.c ================================================================== --- a/generic/tkWindow.c.orig +++ b/generic/tkWindow.c @@ -1619,10 +1619,11 @@ TkBindFree(winPtr->mainPtr); TkDeleteAllImages(winPtr->mainPtr); TkFontPkgFree(winPtr->mainPtr); TkFocusFree(winPtr->mainPtr); TkStylePkgFree(winPtr->mainPtr); + Ttk_TkDestroyedHandler(winPtr->mainPtr->interp); /* * When embedding Tk into other applications, make sure that all * destroy events reach the server. Otherwise the embedding * application may also attempt to destroy the windows, resulting Index: generic/ttk/ttkTheme.c ================================================================== --- a/generic/ttk/ttkTheme.c.orig +++ b/generic/ttk/ttkTheme.c @@ -415,17 +415,10 @@ StylePackageData *pkgPtr = (StylePackageData *)clientData; Tcl_HashSearch search; Tcl_HashEntry *entryPtr; Cleanup *cleanup; - /* - * Cancel any pending ThemeChanged calls: - */ - if (pkgPtr->themeChangePending) { - Tcl_CancelIdleCall(ThemeChangedProc, pkgPtr); - } - /* * Free themes. */ entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search); while (entryPtr != NULL) { @@ -528,10 +521,29 @@ if (!pkgPtr->themeChangePending) { Tcl_DoWhenIdle(ThemeChangedProc, pkgPtr); pkgPtr->themeChangePending = 1; } } + +/* Ttk_TkDestroyedHandler -- + * See bug [310c74ecf440]: idle calls to ThemeChangedProc() + * need to be canceled when Tk is destroyed, since the interp + * may still be active afterward; canceling them from + * Ttk_StylePkgFree() would be too late. + */ +void Ttk_TkDestroyedHandler( + Tcl_Interp* interp) +{ + StylePackageData* pkgPtr = GetStylePackageData(interp); + + /* + * Cancel any pending ThemeChanged calls: + */ + if (pkgPtr->themeChangePending) { + Tcl_CancelIdleCall(ThemeChangedProc, pkgPtr); + } +} /* * Ttk_CreateTheme -- * Create a new theme and register it in the global theme table. *