From cba6aef6d993bf6bdf025d092aef7f718d68b61f Mon Sep 17 00:00:00 2001 From: mdejong Date: Wed, 19 Jun 2002 19:37:53 +0000 Subject: * generic/tkBind.c (TkBindDeadWindow): Handle case where Tk_DestroyWindow is invoked on clipboard and send windows. * generic/tkClipboard.c (TkClipCleanup): Invoke Tk_DestroyWindow to cleanup the dispPtr->clipWindow. Call Tcl_Preserve and Tcl_Release on the window to avoid an invalid memory ref on shutdown. * generic/tkEvent.c (Tk_HandleEvent): Panic if XCreateIC is invoked twice for the same window. This should never happen, the check were just added to make sure it does not since this could lead to crashes in XCloseIM. * generic/tkFocus.c (TkFocusDeadWindow): Handle case where Tk_DestroyWindow is invoked on clipboard and send windows. * generic/tkOption.c (TkOptionDeadWindow): Ditto. * generic/tkWindow.c (TkCloseDisplay): Move deletion of dispPtr->winTable after TkpCloseDisplay call since Tk_DestroyWindow uses it and could be called by TkpCloseDisplay for clipboard/send windows. Also invoke ckfree for the dispPtr instead of doing it in TkpCloseDisplay. (Tk_DestroyWindow): Check for a null winPtr->mainPtr before doing certain cleanup tasks so the we can invoke Tk_DestroyWindow on clipboard and send windows. We need to do this so that XDestroyIC will get invoked for the input contexts of each window. * mac/tkMacXStubs.c (TkpCloseDisplay): Don't free the displayPtr since this is now done in TkCloseDisplay. * unix/tkUnixEvent.c (TkpCloseDisplay, OpenIM): Remove conditional compilation around calls to XCloseIM since I am confident that the crashes related to input contexts has been fixed. Don't free the displayPtr since this is now done in TkCloseDisplay. * unix/tkUnixSend.c (TkSendCleanup): Invoke the Tk_DestroyWindow method to cleanup the special send window. This will call XDestroyIC and thereby avoid a crash in XCloseIM. The send window needs to be Tcl_Preserve and Tcl_Release to avoid an invalid memory ref on shutdown. * win/tkWinX.c (TkpCloseDisplay): Don't free the displayPtr since this is now done in TkCloseDisplay. FossilOrigin-Name: 2b1442c6d82bdff73ad6575cabf7539bf0295292 --- ChangeLog | 47 +++++++++++++++++++++++++++++++++++++++++++++++ generic/tkBind.c | 9 ++++++++- generic/tkClipboard.c | 12 +++++------- generic/tkEvent.c | 6 +++++- generic/tkFocus.c | 10 +++++++++- generic/tkOption.c | 4 ++-- generic/tkWindow.c | 16 ++++++++++++---- mac/tkMacXStubs.c | 3 +-- unix/tkUnixEvent.c | 19 ++++++++----------- unix/tkUnixSend.c | 23 +++++------------------ win/tkWinX.c | 3 +-- 11 files changed, 103 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index b134225..d2ce879 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,50 @@ +2002-06-19 Mo DeJong + + * generic/tkBind.c (TkBindDeadWindow): + Handle case where Tk_DestroyWindow is invoked + on clipboard and send windows. + * generic/tkClipboard.c (TkClipCleanup): + Invoke Tk_DestroyWindow to cleanup the + dispPtr->clipWindow. Call Tcl_Preserve + and Tcl_Release on the window to avoid an + invalid memory ref on shutdown. + * generic/tkEvent.c (Tk_HandleEvent): + Panic if XCreateIC is invoked twice for + the same window. This should never happen, + the check were just added to make sure it + does not since this could lead to crashes + in XCloseIM. + * generic/tkFocus.c (TkFocusDeadWindow): + Handle case where Tk_DestroyWindow is invoked + on clipboard and send windows. + * generic/tkOption.c (TkOptionDeadWindow): Ditto. + * generic/tkWindow.c (TkCloseDisplay): Move + deletion of dispPtr->winTable after TkpCloseDisplay + call since Tk_DestroyWindow uses it and could + be called by TkpCloseDisplay for clipboard/send windows. + Also invoke ckfree for the dispPtr instead of + doing it in TkpCloseDisplay. + (Tk_DestroyWindow): Check for a null winPtr->mainPtr + before doing certain cleanup tasks so the we can + invoke Tk_DestroyWindow on clipboard and send windows. + We need to do this so that XDestroyIC will get invoked + for the input contexts of each window. + * mac/tkMacXStubs.c (TkpCloseDisplay): Don't free + the displayPtr since this is now done in TkCloseDisplay. + * unix/tkUnixEvent.c (TkpCloseDisplay, OpenIM): Remove + conditional compilation around calls to XCloseIM + since I am confident that the crashes related to + input contexts has been fixed. Don't free + the displayPtr since this is now done in TkCloseDisplay. + * unix/tkUnixSend.c (TkSendCleanup): Invoke the + Tk_DestroyWindow method to cleanup the special + send window. This will call XDestroyIC and thereby + avoid a crash in XCloseIM. The send window needs + to be Tcl_Preserve and Tcl_Release to avoid an + invalid memory ref on shutdown. + * win/tkWinX.c (TkpCloseDisplay): Don't free + the displayPtr since this is now done in TkCloseDisplay. + 2002-06-19 Donal K. Fellows * generic/tkStyle.c: TIP#48 style engine. diff --git a/generic/tkBind.c b/generic/tkBind.c index e472d8e..c70a1a5 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.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: tkBind.c,v 1.24 2002/06/15 02:15:51 hobbs Exp $ + * RCS: @(#) $Id: tkBind.c,v 1.25 2002/06/19 19:37:53 mdejong Exp $ */ #include "tkPort.h" @@ -1907,6 +1907,13 @@ TkBindDeadWindow(winPtr) BindInfo *bindInfoPtr; PendingBinding *curPtr; + /* + * Certain special windows like those used for send and clipboard + * have no mainPtr. + */ + if (winPtr->mainPtr == NULL) + return; + bindInfoPtr = (BindInfo *) winPtr->mainPtr->bindInfo; curPtr = bindInfoPtr->pendingList; while (curPtr != NULL) { diff --git a/generic/tkClipboard.c b/generic/tkClipboard.c index 149f65d..c43d621 100644 --- a/generic/tkClipboard.c +++ b/generic/tkClipboard.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: tkClipboard.c,v 1.9 2002/04/12 10:03:02 hobbs Exp $ + * RCS: @(#) $Id: tkClipboard.c,v 1.10 2002/06/19 19:37:54 mdejong Exp $ */ #include "tkInt.h" @@ -649,12 +649,9 @@ TkClipCleanup(dispPtr) dispPtr->applicationAtom); Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom, dispPtr->windowAtom); - /* - * It may be too late to call Tk_DestroyWindow, so just free the - * memory created directly. - */ - ckfree((char *) dispPtr->clipWindow); - dispPtr->clipWindow = NULL; + + Tk_DestroyWindow(dispPtr->clipWindow); + Tcl_Release((ClientData) dispPtr->clipWindow); } } @@ -700,6 +697,7 @@ TkClipInit(interp, dispPtr) if (dispPtr->clipWindow == NULL) { return TCL_ERROR; } + Tcl_Preserve((ClientData) dispPtr->clipWindow); atts.override_redirect = True; Tk_ChangeWindowAttributes(dispPtr->clipWindow, CWOverrideRedirect, &atts); Tk_MakeWindowExist(dispPtr->clipWindow); diff --git a/generic/tkEvent.c b/generic/tkEvent.c index 754b451..009e2f5 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.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: tkEvent.c,v 1.15 2002/06/15 02:08:12 hobbs Exp $ + * RCS: @(#) $Id: tkEvent.c,v 1.16 2002/06/19 19:37:54 mdejong Exp $ */ #include "tkPort.h" @@ -888,6 +888,8 @@ Tk_HandleEvent(eventPtr) preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, XNFontSet, dispPtr->inputXfs, NULL); + if (winPtr->inputContext != NULL) + panic("inputContext not NULL"); winPtr->inputContext = XCreateIC(dispPtr->inputMethod, XNInputStyle, XIMPreeditPosition|XIMStatusNothing, XNClientWindow, winPtr->window, @@ -897,6 +899,8 @@ Tk_HandleEvent(eventPtr) XFree(preedit_attr); } else #endif + if (winPtr->inputContext != NULL) + panic("inputContext not NULL"); winPtr->inputContext = XCreateIC(dispPtr->inputMethod, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, winPtr->window, diff --git a/generic/tkFocus.c b/generic/tkFocus.c index b1ba279..f31d2a3 100644 --- a/generic/tkFocus.c +++ b/generic/tkFocus.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkFocus.c,v 1.8 2002/06/14 22:25:12 jenglish Exp $ + * RCS: @(#) $Id: tkFocus.c,v 1.9 2002/06/19 19:37:54 mdejong Exp $ */ #include "tkInt.h" @@ -813,6 +813,14 @@ TkFocusDeadWindow(winPtr) TkDisplay *dispPtr = winPtr->dispPtr; /* + * Certain special windows like those used for send and clipboard + * have no mainPtr. + */ + + if (winPtr->mainPtr == NULL) + return; + + /* * Search for focus records that refer to this window either as * the top-level window or the current focus window. */ diff --git a/generic/tkOption.c b/generic/tkOption.c index d562e6c..227ae40 100644 --- a/generic/tkOption.c +++ b/generic/tkOption.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: tkOption.c,v 1.13 2002/06/15 21:02:20 mdejong Exp $ + * RCS: @(#) $Id: tkOption.c,v 1.14 2002/06/19 19:37:54 mdejong Exp $ */ #include "tkPort.h" @@ -787,7 +787,7 @@ TkOptionDeadWindow(winPtr) * database. */ - if ((winPtr->mainPtr->winPtr == winPtr) + if ((winPtr->mainPtr != NULL) && (winPtr->mainPtr->winPtr == winPtr) && (winPtr->mainPtr->optionRootPtr != NULL)) { ClearOptionTree(winPtr->mainPtr->optionRootPtr); winPtr->mainPtr->optionRootPtr = NULL; diff --git a/generic/tkWindow.c b/generic/tkWindow.c index e778e40..187dce4 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWindow.c,v 1.49 2002/06/18 23:51:46 dkf Exp $ + * RCS: @(#) $Id: tkWindow.c,v 1.50 2002/06/19 19:37:54 mdejong Exp $ */ #include "tkPort.h" @@ -240,8 +240,6 @@ TkCloseDisplay(TkDisplay *dispPtr) ckfree(dispPtr->name); } - Tcl_DeleteHashTable(&dispPtr->winTable); - if (dispPtr->atomInit) { Tcl_DeleteHashTable(&dispPtr->nameTable); Tcl_DeleteHashTable(&dispPtr->atomTable); @@ -263,6 +261,15 @@ TkCloseDisplay(TkDisplay *dispPtr) TkpCloseDisplay(dispPtr); /* + * Delete winTable after TkpCloseDisplay since special windows + * may need call Tk_DestroyWindow and it checks the winTable. + */ + + Tcl_DeleteHashTable(&dispPtr->winTable); + + ckfree((char *) dispPtr); + + /* * There is more to clean up, we leave it at this for the time being. */ } @@ -1262,7 +1269,7 @@ Tk_DestroyWindow(tkwin) * can be closed and its data structures deleted. */ - if (winPtr->mainPtr->winPtr == winPtr) { + if (winPtr->mainPtr != NULL && winPtr->mainPtr->winPtr == winPtr) { dispPtr->refCount--; if (tsdPtr->mainWindowList == winPtr->mainPtr) { tsdPtr->mainWindowList = winPtr->mainPtr->nextPtr; @@ -1388,6 +1395,7 @@ Tk_DestroyWindow(tkwin) #ifdef TK_USE_INPUT_METHODS if (winPtr->inputContext != NULL) { XDestroyIC(winPtr->inputContext); + winPtr->inputContext = NULL; } #endif /* TK_USE_INPUT_METHODS */ if (winPtr->tagPtr != NULL) { diff --git a/mac/tkMacXStubs.c b/mac/tkMacXStubs.c index 6525c1f..82078b9 100644 --- a/mac/tkMacXStubs.c +++ b/mac/tkMacXStubs.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: tkMacXStubs.c,v 1.14 2002/06/17 20:09:01 hobbs Exp $ + * RCS: @(#) $Id: tkMacXStubs.c,v 1.15 2002/06/19 19:37:55 mdejong Exp $ */ #include "tkInt.h" @@ -184,7 +184,6 @@ TkpCloseDisplay( ckfree((char *) display->screens); } ckfree((char *) display); - ckfree((char *) displayPtr); } /* diff --git a/unix/tkUnixEvent.c b/unix/tkUnixEvent.c index 98132a1..918d66a 100644 --- a/unix/tkUnixEvent.c +++ b/unix/tkUnixEvent.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkUnixEvent.c,v 1.8 2002/06/15 01:54:09 hobbs Exp $ + * RCS: @(#) $Id: tkUnixEvent.c,v 1.9 2002/06/19 19:37:55 mdejong Exp $ */ #include "tkInt.h" @@ -172,24 +172,23 @@ TkpCloseDisplay(dispPtr) XFreeFontSet(dispPtr->display, dispPtr->inputXfs); } #endif -#if ! defined(SOLARIS2) || defined(HAVE_X11R6) if (dispPtr->inputMethod) { /* - * This causes core dumps on some systems (e.g. Solaris 2.3 as of - * 1/6/95), but is OK with X11R6 + * This caused core dumps on some systems (Solaris 2.3 1/6/95). + * The most likely cause of this is a bug in X that accesses + * memory that was already deallocated inside XCloseIM(). + * One can work around this issue by making sure a XDestroyIC() + * gets invoked for each XCreateIC(). */ XCloseIM(dispPtr->inputMethod); } #endif -#endif if (dispPtr->display != 0) { Tcl_DeleteFileHandler(ConnectionNumber(dispPtr->display)); (void) XSync(dispPtr->display, False); (void) XCloseDisplay(dispPtr->display); } - - ckfree((char *) dispPtr); } /* @@ -610,12 +609,10 @@ OpenIM(dispPtr) if (dispPtr->inputMethod) { /* - * This causes core dumps on some systems (e.g. Solaris 2.3 as of - * 1/6/95), but is OK with X11R6 + * This call should not suffer from any core dumping problems + * since we have not allocated any input contexts. */ -#if ! defined (SOLARIS2) || defined (HAVE_X11R6) XCloseIM(dispPtr->inputMethod); -#endif dispPtr->inputMethod = NULL; } } diff --git a/unix/tkUnixSend.c b/unix/tkUnixSend.c index 843360a..ea0d393 100644 --- a/unix/tkUnixSend.c +++ b/unix/tkUnixSend.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkUnixSend.c,v 1.7 2002/06/17 19:42:11 hobbs Exp $ + * RCS: @(#) $Id: tkUnixSend.c,v 1.8 2002/06/19 19:37:55 mdejong Exp $ */ #include "tkPort.h" @@ -1275,25 +1275,11 @@ void TkSendCleanup(dispPtr) TkDisplay *dispPtr; { - TkWindow *winPtr = (TkWindow *) dispPtr->commTkwin; - if (dispPtr->commTkwin != NULL) { - Tk_DeleteEventHandler((Tk_Window) winPtr, PropertyChangeMask, + Tk_DeleteEventHandler(dispPtr->commTkwin, PropertyChangeMask, SendEventProc, (ClientData) dispPtr); - - /* - * We need to manually free all the XIC structures that - * have been allocated in order to avoid a nasty bug in XCloseIM(). - */ - if (winPtr->inputContext != NULL) { - XDestroyIC(winPtr->inputContext); - winPtr->inputContext = NULL; - } - -#ifdef PURIFY - /* Tk_DestroyWindow(dispPtr->commTkwin); */ - ckfree((char *) dispPtr->commTkwin); -#endif + Tk_DestroyWindow(dispPtr->commTkwin); + Tcl_Release((ClientData) dispPtr->commTkwin); dispPtr->commTkwin = NULL; } } @@ -1335,6 +1321,7 @@ SendInit(interp, dispPtr) if (dispPtr->commTkwin == NULL) { panic("Tk_CreateWindow failed in SendInit!"); } + Tcl_Preserve((ClientData) dispPtr->commTkwin); atts.override_redirect = True; Tk_ChangeWindowAttributes(dispPtr->commTkwin, CWOverrideRedirect, &atts); diff --git a/win/tkWinX.c b/win/tkWinX.c index 85e9464..9de5da3 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinX.c,v 1.22 2002/06/17 20:09:01 hobbs Exp $ + * RCS: @(#) $Id: tkWinX.c,v 1.23 2002/06/19 19:37:55 mdejong Exp $ */ #include "tkWinInt.h" @@ -558,7 +558,6 @@ TkpCloseDisplay(dispPtr) ckfree((char *) display->screens); } ckfree((char *) display); - ckfree((char *) dispPtr); } /* -- cgit v0.12