Tcl Source Code

Artifact [c917148257]
Login

Artifact c917148257ac8c7e63c161e41784fee7f8445825:

Attachment "TclEvent_c.txt" to ticket [1589794fff] added by celine_thales 2007-01-22 16:21:03.
void
Tcl_Finalize()
{
    ExitHandler *exitPtr;
    ThreadSpecificData *tsdPtr;

    TclpInitLock();
    if (subsystemsInitialized != 0) {
	subsystemsInitialized = 0;

	tsdPtr = 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.
	 * Note that there is no thread-local storage after this call.
	 */

	Tcl_FinalizeThread();

	/*
	 * Now finalize the Tcl execution environment.  Note that this
	 * must be done after the exit handlers, because there are
	 * order dependencies.
	 */

	TclFinalizeCompExecEnv();
	TclFinalizeEnvironment();

	TclFinalizeEncodingSubsystem();

	if (tclExecutableName != NULL) {
	    ckfree(tclExecutableName);
	    tclExecutableName = NULL;
	}
	if (tclNativeExecutableName != NULL) {
	    ckfree(tclNativeExecutableName);
	    tclNativeExecutableName = NULL;
	}
	if (tclDefaultEncodingDir != NULL) {
	    ckfree(tclDefaultEncodingDir);
	    tclDefaultEncodingDir = NULL;
	}
	
	Tcl_SetPanicProc(NULL);

   // Added to avoid memeory leak
   TclFinalizeThreadData();

	/*
	 * Free synchronization objects.  There really should only be one
	 * thread alive at this moment.
	 */

	TclFinalizeSynchronization();

	/*
	 * We defer unloading of packages until very late 
	 * to avoid memory access issues.  Both exit callbacks and
	 * synchronization variables may be stored in packages.
	 */

	TclFinalizeLoad();

	/*
	 * There shouldn't be any malloc'ed memory after this.
	 */

	TclFinalizeMemorySubsystem();
	inFinalize = 0;
    }
    TclpInitUnlock();
}