Index: generic/tclEvent.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclEvent.c,v
retrieving revision 1.88
diff -u -r1.88 tclEvent.c
--- generic/tclEvent.c	10 Feb 2009 22:49:42 -0000	1.88
+++ generic/tclEvent.c	15 Jun 2009 21:40:30 -0000
@@ -76,13 +76,13 @@
 TCL_DECLARE_MUTEX(exitMutex)
 
 /*
- * This variable is set to 1 when Tcl_Finalize is called, and at the end of
- * its work, it is reset to 0. The variable is checked by TclInExit() to allow
- * different behavior for exit-time processing, e.g. in closing of files and
- * pipes.
+ * This variable is set to 1 when Tcl_Exit is called.  The variable is
+ * checked by TclInExit() to allow different behavior for
+ * exit-time processing, e.g. in closing of files and pipes.
  */
 
-static int inFinalize = 0;
+static int inExit = 0;
+
 static int subsystemsInitialized = 0;
 
 /*
@@ -119,6 +119,8 @@
 static void		HandleBgErrors(ClientData clientData);
 static char *		VwaitVarProc(ClientData clientData, Tcl_Interp *interp,
 			    const char *name1, const char *name2, int flags);
+static void             InvokeExitHandlers(void);
+
 
 /*
  *----------------------------------------------------------------------
@@ -862,6 +864,49 @@
 
     return prevExitProc;
 }
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvokeExitHandlers --
+ *
+ *      Call the registered exit handlers.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	The exit handlers are invoked, and the ExitHandler struct is
+ *      freed.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+InvokeExitHandlers(void) 
+{
+    ExitHandler *exitPtr;
+
+    Tcl_MutexLock(&exitMutex);
+    inExit = 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);
+}
+
 
 /*
  *----------------------------------------------------------------------
@@ -904,7 +949,14 @@
 	 * Use default handling.
 	 */
 
-	Tcl_Finalize();
+	InvokeExitHandlers();
+
+	/*
+	 * This triggers a flush of the Tcl_Channels that may have
+	 * data enqueued.
+	 */
+	TclFinalizeIOSubsystem();
+
 	TclpExit(status);
 	Tcl_Panic("OS exit failed!");
     }
@@ -938,8 +990,8 @@
 void
 TclInitSubsystems(void)
 {
-    if (inFinalize != 0) {
-	Tcl_Panic("TclInitSubsystems called while finalizing");
+    if (inExit != 0) {
+	Tcl_Panic("TclInitSubsystems called while exiting");
     }
 
     if (subsystemsInitialized == 0) {
@@ -993,9 +1045,8 @@
  * Tcl_Finalize --
  *
  *	Shut down Tcl. First calls registered exit handlers, then carefully
- *	shuts down various subsystems.  Called by Tcl_Exit, or should be
- *	invoked by user before the Tcl shared library is being unloaded in
- *	an embedded context.
+ *	shuts down various subsystems.  Should be invoked by user before the
+ *	Tcl shared library is being unloaded in an embedded context.
  *
  * Results:
  *	None.
@@ -1010,28 +1061,10 @@
 Tcl_Finalize(void)
 {
     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);
+    InvokeExitHandlers();   
 
     TclpInitLock();
     if (subsystemsInitialized == 0) {
@@ -1187,7 +1220,6 @@
      */
 
     TclFinalizeMemorySubsystem();
-    inFinalize = 0;
 
   alreadyFinalized:
     TclFinalizeLock();
@@ -1275,7 +1307,7 @@
 int
 TclInExit(void)
 {
-    return inFinalize;
+    return inExit;
 }
 
 /*
