diff options
author | donal.k.fellows@manchester.ac.uk <dkf> | 2000-11-29 15:47:04 (GMT) |
---|---|---|
committer | donal.k.fellows@manchester.ac.uk <dkf> | 2000-11-29 15:47:04 (GMT) |
commit | 6df78e4dbf1352bc96368c7a3b7c151258163cc1 (patch) | |
tree | b7941ad7c36543d32f04b86d132bcac9268b3b8b /generic/tkImage.c | |
parent | acb8bad2a503f787e130e74d4008ea53377c4529 (diff) | |
download | tk-6df78e4dbf1352bc96368c7a3b7c151258163cc1.zip tk-6df78e4dbf1352bc96368c7a3b7c151258163cc1.tar.gz tk-6df78e4dbf1352bc96368c7a3b7c151258163cc1.tar.bz2 |
A better fix for #120819 (all it needed was some Tcl_Preserve()s)
which also requires no documentation changes - the behaviour is now
what you would predict from existing docs (as opposed to a crash!)
Diffstat (limited to 'generic/tkImage.c')
-rw-r--r-- | generic/tkImage.c | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/generic/tkImage.c b/generic/tkImage.c index 7952108..f8d5388 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.9 2000/11/28 11:16:04 dkf Exp $ + * RCS: @(#) $Id: tkImage.c,v 1.10 2000/11/29 15:47:05 dkf Exp $ */ #include "tkInt.h" @@ -69,6 +69,7 @@ typedef struct ImageMaster { * entry). */ Image *instancePtr; /* Pointer to first in list of instances * derived from this name. */ + int deleted; /* Flag set when image is being deleted */ } ImageMaster; typedef struct ThreadSpecificData { @@ -83,7 +84,8 @@ static Tcl_ThreadDataKey dataKey; * Prototypes for local procedures: */ -static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr)); +static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr)); +static void EventuallyDeleteImage _ANSI_ARGS_((ImageMaster *masterPtr)); /* *---------------------------------------------------------------------- @@ -251,6 +253,7 @@ Tk_ImageObjCmd(clientData, interp, objc, objv) masterPtr->tablePtr = &winPtr->mainPtr->imageTable; masterPtr->hPtr = hPtr; masterPtr->instancePtr = NULL; + masterPtr->deleted = 0; Tcl_SetHashValue(hPtr, masterPtr); } else { /* @@ -290,15 +293,18 @@ Tk_ImageObjCmd(clientData, interp, objc, objv) } args[objc] = NULL; } + Tcl_Preserve(masterPtr); if ((*typePtr->createProc)(interp, name, objc, args, typePtr, (Tk_ImageMaster) masterPtr, &masterPtr->masterData) != TCL_OK) { - DeleteImage(masterPtr); + EventuallyDeleteImage(masterPtr); + Tcl_Release(masterPtr); if (oldimage) { ckfree((char *) args); } return TCL_ERROR; } + Tcl_Release(masterPtr); if (oldimage) { ckfree((char *) args); } @@ -322,8 +328,7 @@ Tk_ImageObjCmd(clientData, interp, objc, objv) "\" doesn't exist", (char *) NULL); return TCL_ERROR; } - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - DeleteImage(masterPtr); + DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr)); } break; } @@ -861,7 +866,7 @@ Tk_DeleteImage(interp, name) if (hPtr == NULL) { return; } - DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr)); + DeleteImage((ImageMaster *)Tcl_GetHashValue(hPtr)); } /* @@ -911,6 +916,34 @@ DeleteImage(masterPtr) /* *---------------------------------------------------------------------- * + * EventuallyDeleteImage -- + * + * Arrange for an image to be deleted when it is safe to do so. + * + * Results: + * None. + * + * Side effects: + * Image will get freed, though not until it is no longer + * Tcl_Preserve()d by anything. May be called multiple times on + * the same image without ill effects. + * + *---------------------------------------------------------------------- + */ + +static void +EventuallyDeleteImage(masterPtr) + ImageMaster *masterPtr; /* Pointer to main data structure for image. */ +{ + if (!masterPtr->deleted) { + masterPtr->deleted = 1; + Tcl_EventuallyFree(masterPtr, (Tcl_FreeProc *)DeleteImage); + } +} + +/* + *---------------------------------------------------------------------- + * * TkDeleteAllImages -- * * This procedure is called when an application is deleted. It @@ -934,12 +967,10 @@ TkDeleteAllImages(mainPtr) { Tcl_HashSearch search; Tcl_HashEntry *hPtr; - ImageMaster *masterPtr; for (hPtr = Tcl_FirstHashEntry(&mainPtr->imageTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - DeleteImage(masterPtr); + EventuallyDeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr)); } Tcl_DeleteHashTable(&mainPtr->imageTable); } |