summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--generic/tkPlace.c46
2 files changed, 47 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index d3f67b8..fdefa3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2007-10-25 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkPlace.c: Prevent segfault in place geometry manager.
+ Thanks to Colin McDonald. [Bug 1818491]
+
2007-10-24 Joe English <jenglish@users.sourceforge.net>
* generic/ttk/*.c, win/{ttkWinMonitor,ttkWinTheme,ttkWinXPTheme}.c,
diff --git a/generic/tkPlace.c b/generic/tkPlace.c
index 5272d31..2923578 100644
--- a/generic/tkPlace.c
+++ b/generic/tkPlace.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: tkPlace.c,v 1.22 2007/09/07 00:34:53 dgp Exp $
+ * RCS: @(#) $Id: tkPlace.c,v 1.23 2007/10/25 16:39:23 dgp Exp $
*/
#include "tkInt.h"
@@ -133,6 +133,12 @@ typedef struct Master {
Tk_Window tkwin; /* Tk's token for master window. */
struct Slave *slavePtr; /* First in linked list of slaves placed
* relative to this master. */
+ int *abortPtr; /* If non-NULL, it means that there is a nested
+ * call to RecomputePlacement already working on
+ * this window. *abortPtr may be set to 1 to
+ * abort that nested call. This happens, for
+ * example, if tkwin or any of its slaves
+ * is deleted. */
int flags; /* See below for bit definitions. */
} Master;
@@ -503,6 +509,10 @@ UnlinkSlave(
}
}
}
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
slavePtr->masterPtr = NULL;
}
@@ -537,6 +547,7 @@ CreateMaster(
masterPtr = (Master *) ckalloc(sizeof(Master));
masterPtr->tkwin = tkwin;
masterPtr->slavePtr = NULL;
+ masterPtr->abortPtr = NULL;
masterPtr->flags = 0;
Tcl_SetHashValue(hPtr, masterPtr);
Tk_CreateEventHandler(masterPtr->tkwin, StructureNotifyMask,
@@ -846,14 +857,32 @@ RecomputePlacement(
int masterWidth, masterHeight, masterX, masterY;
double x1, y1, x2, y2;
+ int abort; /* May get set to non-zero to abort this
+ * placement operation. */
+
masterPtr->flags &= ~PARENT_RECONFIG_PENDING;
+
+ /*
+ * Abort any nested call to RecomputePlacement for this window, since
+ * we'll do everything necessary here, and set up so this call
+ * can be aborted if necessary.
+ */
+
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ masterPtr->abortPtr = &abort;
+ abort = 0;
+ Tcl_Preserve((ClientData) masterPtr);
/*
* Iterate over all the slaves for the master. Each slave's geometry can
- * be computed independently of the other slaves.
+ * be computed independently of the other slaves. Changes to the window's
+ * structure could cause almost anything to happen, including deleting the
+ * parent or child. If this happens, we'll be told to abort.
*/
- for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
+ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort;
slavePtr = slavePtr->nextPtr) {
/*
* Step 1: compute size and borderwidth of master, taking into account
@@ -993,6 +1022,9 @@ RecomputePlacement(
|| (height != Tk_Height(slavePtr->tkwin))) {
Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height);
}
+ if (abort) {
+ break;
+ }
/*
* Don't map the slave unless the master is mapped: the slave will
@@ -1012,6 +1044,9 @@ RecomputePlacement(
}
}
}
+
+ masterPtr->abortPtr = NULL;
+ Tcl_Release((ClientData) masterPtr);
}
/*
@@ -1061,7 +1096,10 @@ MasterStructureProc(
Tcl_CancelIdleCall(RecomputePlacement, (ClientData) masterPtr);
}
masterPtr->tkwin = NULL;
- ckfree((char *) masterPtr);
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ Tcl_EventuallyFree((ClientData) masterPtr, TCL_DYNAMIC);
} else if (eventPtr->type == MapNotify) {
/*
* When a master gets mapped, must redo the geometry computation so