Tcl Source Code

Artifact [ffe08db234]
Login

Artifact ffe08db234c4c3481f75f827dd612e585ac0197b:

Attachment "fin.patch" to ticket [1028264fff] added by ferrieux 2009-01-07 07:00:03.
Index: generic/tcl.decls
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tcl.decls,v
retrieving revision 1.164
diff -u -b -r1.164 tcl.decls
--- generic/tcl.decls	18 Dec 2008 06:40:02 -0000	1.164
+++ generic/tcl.decls	6 Jan 2009 23:54:44 -0000
@@ -2276,6 +2276,17 @@
     int Tcl_CloseEx(Tcl_Interp *interp, Tcl_Channel chan, int flags)
 }
 
+
+# Late exit handlers
+
+declare 625 generic {
+    void Tcl_CreateLateExitHandler(Tcl_ExitProc *proc, ClientData clientData)
+}
+
+declare 626 generic {
+    void Tcl_DeleteLateExitHandler(Tcl_ExitProc *proc, ClientData clientData)
+}
+
 ##############################################################################
 
 # Define the platform specific public Tcl interface. These functions are only
Index: generic/tclDecls.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclDecls.h,v
retrieving revision 1.166
diff -u -b -r1.166 tclDecls.h
--- generic/tclDecls.h	18 Dec 2008 06:40:02 -0000	1.166
+++ generic/tclDecls.h	6 Jan 2009 23:54:53 -0000
@@ -3775,6 +3775,18 @@
 EXTERN int		Tcl_CloseEx (Tcl_Interp * interp, Tcl_Channel chan,
 				int flags);
 #endif
+#ifndef Tcl_CreateLateExitHandler_TCL_DECLARED
+#define Tcl_CreateLateExitHandler_TCL_DECLARED
+/* 625 */
+EXTERN void		Tcl_CreateLateExitHandler (Tcl_ExitProc * proc,
+				ClientData clientData);
+#endif
+#ifndef Tcl_DeleteLateExitHandler_TCL_DECLARED
+#define Tcl_DeleteLateExitHandler_TCL_DECLARED
+/* 626 */
+EXTERN void		Tcl_DeleteLateExitHandler (Tcl_ExitProc * proc,
+				ClientData clientData);
+#endif
 
 typedef struct TclStubHooks {
     const struct TclPlatStubs *tclPlatStubs;
@@ -4459,6 +4471,8 @@
     void (*tcl_SetStartupScript) (Tcl_Obj * path, const char * encoding); /* 622 */
     Tcl_Obj * (*tcl_GetStartupScript) (const char ** encodingPtr); /* 623 */
     int (*tcl_CloseEx) (Tcl_Interp * interp, Tcl_Channel chan, int flags); /* 624 */
+    void (*tcl_CreateLateExitHandler) (Tcl_ExitProc * proc, ClientData clientData); /* 625 */
+    void (*tcl_DeleteLateExitHandler) (Tcl_ExitProc * proc, ClientData clientData); /* 626 */
 } TclStubs;
 
 #if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS)
@@ -7031,6 +7045,14 @@
 #define Tcl_CloseEx \
 	(tclStubsPtr->tcl_CloseEx) /* 624 */
 #endif
+#ifndef Tcl_CreateLateExitHandler
+#define Tcl_CreateLateExitHandler \
+	(tclStubsPtr->tcl_CreateLateExitHandler) /* 625 */
+#endif
+#ifndef Tcl_DeleteLateExitHandler
+#define Tcl_DeleteLateExitHandler \
+	(tclStubsPtr->tcl_DeleteLateExitHandler) /* 626 */
+#endif
 
 #endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
 
Index: generic/tclEvent.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclEvent.c,v
retrieving revision 1.86
diff -u -b -r1.86 tclEvent.c
--- generic/tclEvent.c	9 Dec 2008 20:16:29 -0000	1.86
+++ generic/tclEvent.c	6 Jan 2009 23:54:55 -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 @@
 /*
  *----------------------------------------------------------------------
  *
+ * Tcl_CreateLateExitHandler --
+ *
+ *	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
+Tcl_CreateLateExitHandler(
+    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 @@
 /*
  *----------------------------------------------------------------------
  *
+ * Tcl_DeleteLateExitHandler --
+ *
+ *	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
+Tcl_DeleteLateExitHandler(
+    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/tclStubInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclStubInit.c,v
retrieving revision 1.177
diff -u -b -r1.177 tclStubInit.c
--- generic/tclStubInit.c	18 Dec 2008 04:38:01 -0000	1.177
+++ generic/tclStubInit.c	6 Jan 2009 23:55:03 -0000
@@ -1150,6 +1150,8 @@
     Tcl_SetStartupScript, /* 622 */
     Tcl_GetStartupScript, /* 623 */
     Tcl_CloseEx, /* 624 */
+    Tcl_CreateLateExitHandler, /* 625 */
+    Tcl_DeleteLateExitHandler, /* 626 */
 };
 
 /* !END!: Do not edit above this line. */
Index: win/tclWinSock.c
===================================================================
RCS file: /cvsroot/tcl/tcl/win/tclWinSock.c,v
retrieving revision 1.64
diff -u -b -r1.64 tclWinSock.c
--- win/tclWinSock.c	18 Dec 2008 01:14:17 -0000	1.64
+++ win/tclWinSock.c	6 Jan 2009 23:55:17 -0000
@@ -232,7 +232,7 @@
 
     if (!initialized) {
 	initialized = 1;
-	Tcl_CreateExitHandler(SocketExitHandler, (ClientData) NULL);
+	Tcl_CreateLateExitHandler(SocketExitHandler, (ClientData) NULL);
 
 	/*
 	 * Create the async notification window with a new class. We must