summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--generic/tclEvent.c48
2 files changed, 30 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index f05e644..bd9a33d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-07-30 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tclEvent.c (Tcl_Finalize): Re-organized Tcl_Finalize
+ so that Tcl_ExitProc's that call Tcl_Finalize recursively do not
+ cause deadlock. [Patch 999084 fixes Tk Bug 714956]
+
2004-07-30 Daniel Steffen <das@users.sourceforge.net>
* unix/configure:
diff --git a/generic/tclEvent.c b/generic/tclEvent.c
index 67ec728..059871c 100644
--- a/generic/tclEvent.c
+++ b/generic/tclEvent.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: tclEvent.c,v 1.28.2.8 2004/07/21 01:30:57 hobbs Exp $
+ * RCS: @(#) $Id: tclEvent.c,v 1.28.2.9 2004/07/30 15:15:57 dgp Exp $
*/
#include "tclInt.h"
@@ -783,6 +783,29 @@ void
Tcl_Finalize()
{
ExitHandler *exitPtr;
+
+ /*
+ * Invoke exit handlers first.
+ */
+
+ Tcl_MutexLock(&exitMutex);
+ inFinalize = 1;
+ for (exitPtr = firstExitPtr; exitPtr != NULL; exitPtr = firstExitPtr) {
+ /*
+ * Be careful to remove the handler from the list before
+ * invoking its callback. This protects us against
+ * double-freeing if the callback should call
+ * Tcl_DeleteExitHandler on itself.
+ */
+
+ firstExitPtr = exitPtr->nextPtr;
+ Tcl_MutexUnlock(&exitMutex);
+ (*exitPtr->proc)(exitPtr->clientData);
+ ckfree((char *) exitPtr);
+ Tcl_MutexLock(&exitMutex);
+ }
+ firstExitPtr = NULL;
+ Tcl_MutexUnlock(&exitMutex);
TclpInitLock();
if (subsystemsInitialized != 0) {
@@ -796,29 +819,6 @@ Tcl_Finalize()
(void) TCL_TSD_INIT(&dataKey);
/*
- * Invoke exit handlers first.
- */
-
- Tcl_MutexLock(&exitMutex);
- inFinalize = 1;
- for (exitPtr = firstExitPtr; exitPtr != NULL; exitPtr = firstExitPtr) {
- /*
- * Be careful to remove the handler from the list before
- * invoking its callback. This protects us against
- * double-freeing if the callback should call
- * Tcl_DeleteExitHandler on itself.
- */
-
- firstExitPtr = exitPtr->nextPtr;
- Tcl_MutexUnlock(&exitMutex);
- (*exitPtr->proc)(exitPtr->clientData);
- ckfree((char *) exitPtr);
- Tcl_MutexLock(&exitMutex);
- }
- firstExitPtr = NULL;
- Tcl_MutexUnlock(&exitMutex);
-
- /*
* Clean up after the current thread now, after exit handlers.
* In particular, the testexithandler command sets up something
* that writes to standard output, which gets closed.