Tcl Source Code

Check-in [c3634cbd75]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Changed finalization to move DLL unloading until the very last moment to avoid referencing memory for Mutex's and Thread Local Storage inside DLLs.

Fixed the thread send command to unlink the result from the global result list while still inside the mutex.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-1-branch-old
Files: files | file ages | folders
SHA1: c3634cbd75f20e58573b3558d28692c335604c77
User & Date: welch 1999-04-03 01:35:19
Context
1999-04-03
01:46
Change log entry for Tcl_ConditionNotify and Tcl_ConditionWait check-in: 523bfb774e user: welch tags: core-8-1-branch-old
01:35
Changed finalization to move DLL unloading until the very last moment to avoid referencing memory fo... check-in: c3634cbd75 user: welch tags: core-8-1-branch-old
01:19
*** empty log message *** check-in: 11b0722d47 user: stanton tags: core-8-1-branch-old
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to generic/tclEvent.c.

     7      7    *
     8      8    * Copyright (c) 1990-1994 The Regents of the University of California.
     9      9    * Copyright (c) 1994-1998 Sun Microsystems, Inc.
    10     10    *
    11     11    * See the file "license.terms" for information on usage and redistribution
    12     12    * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    13     13    *
    14         - * RCS: @(#) $Id: tclEvent.c,v 1.1.2.9 1999/03/30 22:29:02 stanton Exp $
           14  + * RCS: @(#) $Id: tclEvent.c,v 1.1.2.10 1999/04/03 01:35:19 welch Exp $
    15     15    */
    16     16   
    17     17   #include "tclInt.h"
    18     18   #include "tclPort.h"
    19     19   
    20     20   /*
    21     21    * The data structure below is used to report background errors.  One
................................................................................
   797    797   }
   798    798   
   799    799   /*
   800    800    *----------------------------------------------------------------------
   801    801    *
   802    802    * Tcl_Finalize --
   803    803    *
   804         - *	Runs the exit handlers to allow Tcl to clean up its state.
          804  + *	Shut down Tcl.  First calls registered exit handlers, then
          805  + *	carefully shuts down various subsystems.
   805    806    *	Called by Tcl_Exit or when the Tcl shared library is being 
   806    807    *	unloaded.
   807    808    *
   808    809    * Results:
   809    810    *	None.
   810    811    *
   811    812    * Side effects:
................................................................................
   852    853   	 * In particular, the testexithandler command sets up something
   853    854   	 * that writes to standard output, which gets closed.
   854    855   	 * Note that there is no thread-local storage after this call.
   855    856   	 */
   856    857       
   857    858   	Tcl_FinalizeThread();
   858    859   
   859         -	/*
   860         -	 * We defer unloading of packages until after any user callbacks
   861         -	 * are invoked to avoid memory access issues.
   862         -	 */
   863         -
   864         -	TclFinalizeLoad();
   865         -
   866    860   	/*
   867    861   	 * Now finalize the Tcl execution environment.  Note that this
   868    862   	 * must be done after the exit handlers, because there are
   869    863   	 * order dependencies.
   870    864   	 */
   871    865   
   872    866   	TclFinalizeCompExecEnv();
................................................................................
   896    890   	/*
   897    891   	 * Free synchronization objects.  There really should only be one
   898    892   	 * thread alive at this moment.
   899    893   	 */
   900    894   
   901    895   	TclFinalizeSynchronization();
   902    896   
          897  +	/*
          898  +	 * We defer unloading of packages until very late 
          899  +	 * to avoid memory access issues.  Both exit callbacks and
          900  +	 * synchronization variables may be stored in packages.
          901  +	 */
          902  +
          903  +	TclFinalizeLoad();
          904  +
   903    905   	/*
   904    906   	 * There shouldn't be any malloc'ed memory after this.
   905    907   	 */
   906    908   
   907    909   	TclFinalizeMemorySubsystem();
   908    910   	inFinalize = 0;
   909    911       }

Changes to generic/tclLoad.c.

     5      5    *	on all platforms) of Tcl's dynamic loading facilities.
     6      6    *
     7      7    * Copyright (c) 1995-1997 Sun Microsystems, Inc.
     8      8    *
     9      9    * See the file "license.terms" for information on usage and redistribution
    10     10    * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    11     11    *
    12         - * RCS: @(#) $Id: tclLoad.c,v 1.1.2.4 1999/03/30 22:29:03 stanton Exp $
           12  + * RCS: @(#) $Id: tclLoad.c,v 1.1.2.5 1999/04/03 01:35:19 welch Exp $
    13     13    */
    14     14   
    15     15   #include "tclInt.h"
    16     16   
    17     17   /*
    18     18    * The following structure describes a package that has been loaded
    19     19    * either dynamically (with the "load" command) or statically (as
................................................................................
   629    629    */
   630    630   
   631    631   void
   632    632   TclFinalizeLoad()
   633    633   {
   634    634       LoadedPackage *pkgPtr;
   635    635   
   636         -    Tcl_MutexLock(&packageMutex);
          636  +    /*
          637  +     * No synchronization here because there should just be
          638  +     * one thread alive at this point.  Logically, 
          639  +     * packageMutex should be grabbed at this point, but
          640  +     * the Mutexes get finalized before the call to this routine.
          641  +     * The only subsystem left alive at this point is the
          642  +     * memory allocator.
          643  +     */
          644  +
   637    645       while (firstPackagePtr != NULL) {
   638    646   	pkgPtr = firstPackagePtr;
   639    647   	firstPackagePtr = pkgPtr->nextPtr;
   640    648   	if (pkgPtr->fileName[0] != '\0') {
   641    649   	    TclpUnloadFile(pkgPtr->clientData);
   642    650   	}
   643    651   	ckfree(pkgPtr->fileName);
   644    652   	ckfree(pkgPtr->packageName);
   645    653   	ckfree((char *) pkgPtr);
   646    654       }
   647         -    Tcl_MutexUnlock(&packageMutex);
   648    655   }

Changes to generic/tclThreadTest.c.

     7      7    *	Conservation Through Innovation, Limited, with their permission.
     8      8    *
     9      9    * Copyright (c) 1998 by Sun Microsystems, Inc.
    10     10    *
    11     11    * See the file "license.terms" for information on usage and redistribution
    12     12    * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    13     13    *
    14         - * RCS: @(#) $Id: tclThreadTest.c,v 1.1.2.7 1999/04/03 01:19:48 stanton Exp $
           14  + * RCS: @(#) $Id: tclThreadTest.c,v 1.1.2.8 1999/04/03 01:35:19 welch Exp $
    15     15    */
    16     16   
    17     17   #include "tclInt.h"
    18     18   
    19     19   #ifdef TCL_THREADS
    20     20   /*
    21     21    * Each thread has an single instance of the following structure.  There
................................................................................
   722    722   
   723    723       /* 
   724    724        * Block on the results and then get them.
   725    725        */
   726    726   
   727    727       Tcl_ResetResult(interp);
   728    728       Tcl_MutexLock(&threadMutex);
   729         -    if (resultPtr->result == NULL) {
          729  +    while (resultPtr->result == NULL) {
   730    730           Tcl_ConditionWait(&resultPtr->done, &threadMutex, NULL);
   731    731       }
          732  +
          733  +    /*
          734  +     * Unlink result from the result list.
          735  +     */
          736  +
          737  +    if (resultPtr->prevPtr) {
          738  +	resultPtr->prevPtr->nextPtr = resultPtr->nextPtr;
          739  +    } else {
          740  +	resultList = resultPtr->nextPtr;
          741  +    }
          742  +    if (resultPtr->nextPtr) {
          743  +	resultPtr->nextPtr->prevPtr = resultPtr->prevPtr;
          744  +    }
          745  +    resultPtr->eventPtr = NULL;
          746  +    resultPtr->nextPtr = NULL;
          747  +    resultPtr->prevPtr = NULL;
          748  +
   732    749       Tcl_MutexUnlock(&threadMutex);
          750  +
   733    751       if (resultPtr->code != TCL_OK) {
   734    752   	if (resultPtr->errorCode) {
   735    753   	    Tcl_SetErrorCode(interp, resultPtr->errorCode, NULL);
   736    754   	    ckfree(resultPtr->errorCode);
   737    755   	}
   738    756   	if (resultPtr->errorInfo) {
   739    757   	    Tcl_AddErrorInfo(interp, resultPtr->errorInfo);
................................................................................
   740    758   	    ckfree(resultPtr->errorInfo);
   741    759   	}
   742    760       }
   743    761       Tcl_SetResult(interp, resultPtr->result, TCL_DYNAMIC);
   744    762       TclFinalizeCondition(&resultPtr->done);
   745    763       code = resultPtr->code;
   746    764   
   747         -    if (resultPtr->prevPtr) {
   748         -	resultPtr->prevPtr->nextPtr = resultPtr->nextPtr;
   749         -    } else {
   750         -	resultList = resultPtr->nextPtr;
   751         -    }
   752         -    if (resultPtr->nextPtr) {
   753         -	resultPtr->nextPtr->prevPtr = resultPtr->prevPtr;
   754         -    }
   755         -    resultPtr->eventPtr = NULL;
   756         -    resultPtr->nextPtr = NULL;
   757         -    resultPtr->prevPtr = NULL;
   758         -
   759    765       ckfree((char *) resultPtr);
   760    766   
   761    767       return code;
   762    768   }
   763    769   
   764    770   
   765    771   /*