summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--generic/tclEvent.c17
-rw-r--r--generic/tclIO.c3
-rw-r--r--generic/tclInt.h3
-rw-r--r--unix/tclUnixPipe.c23
-rw-r--r--win/tclWinPipe.c11
6 files changed, 58 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 15a1fc4..8ba2b0e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2005-06-22 Kevin Kenny <kennykb@acm.org>
+
+ * generic/tclInt.h: Changed the finalization
+ * generic/tclEvent.c (Tcl_Finalize): logic to defer the
+ * generic/tclIO.c (TclFinalizeIOSubsystem): shutdown of the pipe
+ * unix/tclUnixPipe.c (TclFinalizePipes): management until after
+ * win/tclWinPipe.c (TclFinalizePipes): all channels have been
+ closed, in order to avoid a situation where the Windows
+ PipeCloseProc2 would re-establish the exit handler after
+ exit handlers had already run, corrupting the heap.
+ [Bug #1225727]
+
2005-06-22 Andreas Kupries <andreask@activestate.com>
* generic/tclInt.h: Followup to change made on 2005-06-18 by
diff --git a/generic/tclEvent.c b/generic/tclEvent.c
index 059871c..81b6b2d 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.9 2004/07/30 15:15:57 dgp Exp $
+ * RCS: @(#) $Id: tclEvent.c,v 1.28.2.10 2005/06/22 19:35:15 kennykb Exp $
*/
#include "tclInt.h"
@@ -895,11 +895,26 @@ Tcl_Finalize()
TclResetFilesystem();
/*
+ * There have been several bugs in the past that cause
+ * exit handlers to be established during Tcl_Finalize
+ * processing. Such exit handlers leave malloc'ed memory,
+ * and Tcl_FinalizeThreadAlloc or Tcl_FinalizeMemorySubsystem
+ * will result in a corrupted heap. The result can be a
+ * mysterious crash on process exit. Check here that
+ * nobody's done this.
+ */
+
+ if ( firstExitPtr != NULL ) {
+ Tcl_Panic( "exit handlers were created during Tcl_Finalize" );
+ }
+
+ /*
* There shouldn't be any malloc'ed memory after this.
*/
#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) && !defined(TCL_MEM_DEBUG) && !defined(PURIFY)
TclFinalizeThreadAlloc();
#endif
+
TclFinalizeMemorySubsystem();
inFinalize = 0;
}
diff --git a/generic/tclIO.c b/generic/tclIO.c
index 46ebf28..f983a9a 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.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: tclIO.c,v 1.61.2.10 2005/04/14 07:10:06 davygrvy Exp $
+ * RCS: @(#) $Id: tclIO.c,v 1.61.2.11 2005/06/22 19:35:16 kennykb Exp $
*/
#include "tclInt.h"
@@ -274,6 +274,7 @@ TclFinalizeIOSubsystem()
statePtr->flags |= CHANNEL_DEAD;
}
}
+ TclpFinalizePipes();
}
diff --git a/generic/tclInt.h b/generic/tclInt.h
index c0f1982..23bd5aa 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -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: tclInt.h,v 1.118.2.13 2005/06/22 16:49:28 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclInt.h,v 1.118.2.14 2005/06/22 19:35:18 kennykb Exp $
*/
#ifndef _TCLINT
@@ -1721,6 +1721,7 @@ EXTERN int TclpDeleteFile _ANSI_ARGS_((CONST char *path));
EXTERN void TclpFinalizeCondition _ANSI_ARGS_((
Tcl_Condition *condPtr));
EXTERN void TclpFinalizeMutex _ANSI_ARGS_((Tcl_Mutex *mutexPtr));
+EXTERN void TclpFinalizePipes _ANSI_ARGS_((void));
EXTERN void TclpFinalizeThreadData _ANSI_ARGS_((
Tcl_ThreadDataKey *keyPtr));
EXTERN void TclpFinalizeThreadDataKey _ANSI_ARGS_((
diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c
index f410fc3..dd9bc1c 100644
--- a/unix/tclUnixPipe.c
+++ b/unix/tclUnixPipe.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: tclUnixPipe.c,v 1.23.2.3 2005/01/27 22:53:36 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclUnixPipe.c,v 1.23.2.4 2005/06/22 19:36:35 kennykb Exp $
*/
#include "tclInt.h"
@@ -1247,3 +1247,24 @@ Tcl_PidObjCmd(dummy, interp, objc, objv)
}
return TCL_OK;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizePipes --
+ *
+ * Cleans up the pipe subsystem from Tcl_FinalizeThread
+ *
+ * Results:
+ * None.
+ *
+ * This procedure carries out no operation on Unix.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizePipes()
+{
+}
+
diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c
index 8dfc2ad..de56e33 100644
--- a/win/tclWinPipe.c
+++ b/win/tclWinPipe.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: tclWinPipe.c,v 1.33.2.11 2005/06/21 19:07:58 kennykb Exp $
+ * RCS: @(#) $Id: tclWinPipe.c,v 1.33.2.12 2005/06/22 19:36:35 kennykb Exp $
*/
#include "tclWinInt.h"
@@ -201,7 +201,6 @@ static DWORD WINAPI PipeReaderThread(LPVOID arg);
static void PipeSetupProc(ClientData clientData, int flags);
static void PipeWatchProc(ClientData instanceData, int mask);
static DWORD WINAPI PipeWriterThread(LPVOID arg);
-static void ProcExitHandler(ClientData clientData);
static int TempFileName(WCHAR name[MAX_PATH]);
static int WaitForRead(PipeInfo *infoPtr, int blocking);
@@ -263,7 +262,6 @@ PipeInit()
if (!initialized) {
initialized = 1;
procList = NULL;
- Tcl_CreateExitHandler(ProcExitHandler, NULL);
}
Tcl_MutexUnlock(&pipeMutex);
}
@@ -304,7 +302,7 @@ PipeExitHandler(
/*
*----------------------------------------------------------------------
*
- * ProcExitHandler --
+ * TclpFinalizePipes --
*
* This function is called to cleanup the process list before
* Tcl is unloaded.
@@ -318,9 +316,8 @@ PipeExitHandler(
*----------------------------------------------------------------------
*/
-static void
-ProcExitHandler(
- ClientData clientData) /* Old window proc */
+void
+TclpFinalizePipes()
{
Tcl_MutexLock(&pipeMutex);
initialized = 0;