Attachment "fin2.patch" to
ticket [1028264fff]
added by
ferrieux
2009-01-14 04:51:31.
Index: generic/tclEvent.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclEvent.c,v
retrieving revision 1.86
diff -b -u -r1.86 tclEvent.c
--- generic/tclEvent.c 9 Dec 2008 20:16:29 -0000 1.86
+++ generic/tclEvent.c 13 Jan 2009 21:46:49 -0000
@@ -51,7 +51,7 @@
} ErrAssocData;
/*
- * For each exit handler created with a call to Tcl_CreateExitHandler there is
+ * For each exit handler created with a call to Tcl_Create(Late)ExitHandler there is
* a structure of the following type:
*/
@@ -70,6 +70,9 @@
static ExitHandler *firstExitPtr = NULL;
/* First in list of all exit handlers for
* application. */
+static ExitHandler *firstLateExitPtr = NULL;
+ /* First in list of all late exit handlers for
+ * application. */
TCL_DECLARE_MUTEX(exitMutex)
/*
@@ -633,6 +636,39 @@
/*
*----------------------------------------------------------------------
*
+ * TclCreateLateExitHandler --
+ *
+ * Arrange for a given function to be invoked after all pre-thread cleanups
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Proc will be invoked with clientData as argument when the application
+ * exits.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclCreateLateExitHandler(
+ Tcl_ExitProc *proc, /* Function to invoke. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr;
+
+ exitPtr = (ExitHandler *) ckalloc(sizeof(ExitHandler));
+ exitPtr->proc = proc;
+ exitPtr->clientData = clientData;
+ Tcl_MutexLock(&exitMutex);
+ exitPtr->nextPtr = firstLateExitPtr;
+ firstLateExitPtr = exitPtr;
+ Tcl_MutexUnlock(&exitMutex);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_DeleteExitHandler --
*
* This function cancels an existing exit handler matching proc and
@@ -676,6 +712,49 @@
/*
*----------------------------------------------------------------------
*
+ * TclDeleteLateExitHandler --
+ *
+ * This function cancels an existing late exit handler matching proc and
+ * clientData, if such a handler exits.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there is a late exit handler corresponding to proc and clientData then
+ * it is canceled; if no such handler exists then nothing happens.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclDeleteLateExitHandler(
+ Tcl_ExitProc *proc, /* Function that was previously registered. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ ExitHandler *exitPtr, *prevPtr;
+
+ Tcl_MutexLock(&exitMutex);
+ for (prevPtr = NULL, exitPtr = firstLateExitPtr; exitPtr != NULL;
+ prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) {
+ if ((exitPtr->proc == proc)
+ && (exitPtr->clientData == clientData)) {
+ if (prevPtr == NULL) {
+ firstLateExitPtr = exitPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = exitPtr->nextPtr;
+ }
+ ckfree((char *) exitPtr);
+ break;
+ }
+ }
+ Tcl_MutexUnlock(&exitMutex);
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_CreateThreadExitHandler --
*
* Arrange for a given function to be invoked just before the current
@@ -977,6 +1056,27 @@
Tcl_FinalizeThread();
/*
+ * Now invoke late (process-wide) exit handlers.
+ */
+
+ Tcl_MutexLock(&exitMutex);
+ for (exitPtr = firstLateExitPtr; exitPtr != NULL; exitPtr = firstLateExitPtr) {
+ /*
+ * 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_DeleteLateExitHandler on itself.
+ */
+
+ firstLateExitPtr = exitPtr->nextPtr;
+ Tcl_MutexUnlock(&exitMutex);
+ exitPtr->proc(exitPtr->clientData);
+ ckfree((char *) exitPtr);
+ Tcl_MutexLock(&exitMutex);
+ }
+ firstLateExitPtr = NULL;
+ Tcl_MutexUnlock(&exitMutex);
+
+ /*
* Now finalize the Tcl execution environment. Note that this must be done
* after the exit handlers, because there are order dependencies.
*/
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.413
diff -b -u -r1.413 tclInt.h
--- generic/tclInt.h 13 Jan 2009 20:30:03 -0000 1.413
+++ generic/tclInt.h 13 Jan 2009 21:46:54 -0000
@@ -2640,6 +2640,10 @@
int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int TclFileRenameCmd(Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE void TclCreateLateExitHandler (Tcl_ExitProc * proc,
+ ClientData clientData);
+MODULE_SCOPE void TclDeleteLateExitHandler (Tcl_ExitProc * proc,
+ ClientData clientData);
MODULE_SCOPE void TclFinalizeAllocSubsystem(void);
MODULE_SCOPE void TclFinalizeAsync(void);
MODULE_SCOPE void TclFinalizeDoubleConversion(void);
Index: win/tclWinSock.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinSock.c,v
retrieving revision 1.64
diff -b -u -r1.64 tclWinSock.c
--- win/tclWinSock.c 18 Dec 2008 01:14:17 -0000 1.64
+++ win/tclWinSock.c 13 Jan 2009 21:46:58 -0000
@@ -232,7 +232,7 @@
if (!initialized) {
initialized = 1;
- Tcl_CreateExitHandler(SocketExitHandler, (ClientData) NULL);
+ TclCreateLateExitHandler(SocketExitHandler, (ClientData) NULL);
/*
* Create the async notification window with a new class. We must