From bac92cbfb391c2766bfaed11eb16bd73abbed30a Mon Sep 17 00:00:00 2001 From: dkf Date: Mon, 7 Jul 2003 09:35:58 +0000 Subject: Fixed [Bug 749353] by making the removal of masters from the global image table aggressive when the interp is being deleted, and making the deletion code always check to see whether it should actually be deleting an entry or not. No tests as it comes under the heading of crash-on-bug, and the bug is not easy to excite (it requires a full script and interpreter deletion with lots of events about.) --- ChangeLog | 6 ++++++ generic/tkImage.c | 28 +++++++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2e264fe..e61842b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2003-07-07 Donal K. Fellows + + * generic/tkImage.c (TkDeleteAllImages,etc.): Stopped the deleting + of hash entries from a table that has just been deleted by this + function when some images are Tcl_Preserve()d... [Bug 749353] + 2003-07-03 Jim Ingham * macosx/tkMacOSXColor.c (GetControlPartColor): Use diff --git a/generic/tkImage.c b/generic/tkImage.c index 651c675..a27a446 100644 --- a/generic/tkImage.c +++ b/generic/tkImage.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkImage.c,v 1.20 2003/05/08 09:35:41 dkf Exp $ + * RCS: @(#) $Id: tkImage.c,v 1.21 2003/07/07 09:35:58 dkf Exp $ */ #include "tkInt.h" @@ -87,7 +87,8 @@ static Tcl_ThreadDataKey dataKey; */ static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr)); -static void EventuallyDeleteImage _ANSI_ARGS_((ImageMaster *masterPtr)); +static void EventuallyDeleteImage _ANSI_ARGS_((ImageMaster *masterPtr, + int forgetImageHashNow)); /* *---------------------------------------------------------------------- @@ -317,7 +318,7 @@ Tk_ImageObjCmd(clientData, interp, objc, objv) if ((*typePtr->createProc)(interp, name, objc, args, typePtr, (Tk_ImageMaster) masterPtr, &masterPtr->masterData) != TCL_OK) { - EventuallyDeleteImage(masterPtr); + EventuallyDeleteImage(masterPtr, 0); Tcl_Release((ClientData) masterPtr); if (oldimage) { ckfree((char *) args); @@ -553,6 +554,9 @@ Tk_NameOfImage(imageMaster) { ImageMaster *masterPtr = (ImageMaster *) imageMaster; + if (masterPtr->hPtr == NULL) { + return NULL; + } return Tcl_GetHashKey(masterPtr->tablePtr, masterPtr->hPtr); } @@ -677,7 +681,10 @@ Tk_FreeImage(image) */ if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) { - Tcl_DeleteHashEntry(masterPtr->hPtr); + if (masterPtr->hPtr != NULL) { + Tcl_DeleteHashEntry(masterPtr->hPtr); + } + Tcl_Release((ClientData) masterPtr->winPtr); ckfree((char *) masterPtr); } } @@ -952,7 +959,9 @@ DeleteImage(masterPtr) (*typePtr->deleteProc)(masterPtr->masterData); } if (masterPtr->instancePtr == NULL) { - Tcl_DeleteHashEntry(masterPtr->hPtr); + if (masterPtr->hPtr != NULL) { + Tcl_DeleteHashEntry(masterPtr->hPtr); + } Tcl_Release((ClientData) masterPtr->winPtr); ckfree((char *) masterPtr); } else { @@ -979,9 +988,14 @@ DeleteImage(masterPtr) */ static void -EventuallyDeleteImage(masterPtr) +EventuallyDeleteImage(masterPtr, forgetImageHashNow) ImageMaster *masterPtr; /* Pointer to main data structure for image. */ + int forgetImageHashNow; /* Flag to say whether the hash table is + * about to vanish. */ { + if (forgetImageHashNow) { + masterPtr->hPtr = NULL; + } if (!masterPtr->deleted) { masterPtr->deleted = 1; Tcl_EventuallyFree((ClientData) masterPtr, @@ -1018,7 +1032,7 @@ TkDeleteAllImages(mainPtr) for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - EventuallyDeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr)); + EventuallyDeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr), 1); } Tcl_DeleteHashTable(&mainPtr->imageTable); } -- cgit v0.12