Tcl Source Code

View Ticket
Login
Ticket UUID: 615304
Title: Tcl_InitStubs crash/exception
Type: Bug Version: obsolete: 8.4.0
Submitter: nobody Created on: 2002-09-27 00:21:07
Subsystem: 50. Embedding Support Assigned To: davygrvy
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2002-12-04 14:02:10
Resolution: None Closed By: hobbs
    Closed on: 2002-12-04 07:02:10
Description:
The error primarily involves the Tcl_InitStubs 
function.

This is the scenario that causes the error:

1. Upon being loaded the component first calls 
LoadLibrary for both the Tcl and Tk DLLs.  Next, 
some other initialization functions are called.  
Finally, Tcl_InitStubs is called successfully.  
Initialization is now complete.

2. Various Tcl/Tk calls are made without any 
problems.

3. During component shutdown, Tcl_Finalize is 
called followed by FreeLibrary on both the Tcl and 
Tk DLLs.

4. Later, when the component is loaded again into 
the same process (it's still running), it calls 
LoadLibrary for both the Tcl and Tk DLLs [again] 
and calls Tcl_InitStubs [again] as part of it's 
initialization routine. An exception is immediately 
thrown (unable to even step-into the code for 
Tcl_InitStubs).

It is my impression that somehow the Tcl_InitStubs 
function might be getting corrupted by 
Tcl_Finalize.  

If this behavior is by design, I apologize in advance 
for this bug report.

JJM
User Comments: hobbs added on 2002-12-04 14:02:10:
Logged In: YES 
user_id=72656

The solution is to not do the tclStubsPtr check in 
tclStubLib.c  Dave's work-around it also good, but you can 
make the tclStubLib.c change yourself if you compile 
yourself, since that part is statically loaded into your code.  I 
plan on making that standard for future versions of Tcl.

davygrvy added on 2002-11-28 06:11:00:
Logged In: YES 
user_id=7549

I don't know if a doc fix is needed..  Seems like an edge case.

nobody added on 2002-10-03 14:16:10:
Logged In: NO 

That works for me...  Sounds like it's a doc fix... :)

davygrvy added on 2002-10-03 12:18:13:
Logged In: YES 
user_id=7549

Ahh!  I agree with your detective work.

As there isn't any linkage from Tcl to your 
extension/application when using Stubs, Tcl_Finalize can not 
take on responsibility to affect a global in the Stubs library 
used, so it looks like you should set it manually to NULL, 
now armed with the knowledge of how it works.

void
UnloadIt(Tcl_Interp *interp)
{
    extern TclStubs *tclStubsPtr;

    Tcl_DeleteInterp(interp);
    Tcl_Finalize();
    FreeLibrary(hTclModule);
    tclStubsPtr = NULL;
}

I guess I was lucky in that Tcl had loaded into the same 
place for the test case I had made.

Does this solve it for you?

nobody added on 2002-10-03 02:50:34:
Logged In: NO 

When I stepped through the code (several times) to 
diagnose the problem, I noticed that the 
variable "tclStubsPtr" is never being reset to NULL.  
Additionally, it does not appear to ever be explicitly 
initialized to NULL.

CONST char *
Tcl_InitStubs (interp, version, exact)
    Tcl_Interp *interp;
    CONST char *version;
    int exact;
{
    CONST char *actualVersion;
    TclStubs *tmp;
   
    if (!tclStubsPtr) {

//*** NOTE: The first time through here, the tclStubsPtr 
is set to the one from the interp.
//*** Since the tclStubsPtr is never explicitly reset (at 
least, not that I can find), this code is not executed the 
second time through.

tclStubsPtr = HasStubSupport(interp);
if (!tclStubsPtr) {
            return NULL;
        }
    }

//*** I'm not sure what the "tmp" variable here is doing.
//*** Upon close examination, I believe the cause of the 
crash is a bad address for Tcl_PkgRequireEx, as this is a 
macro defined to be "tclStubsPtr->tcl_PkgRequireEx".
//*** Since the tclStubsPtr variable does not really exist 
in a known state after the first time around (or really, at 
all), by the time the second time roles around there is 
somehow total garbage in the tclStubsPtr that a simple 
call to HasStubSupport seems to fix.  This is due to the 
fact that Tcl_CreateInterp actually sets up the internal 
stubs table inside the interp prior to Tcl_InitStubs ever 
being called, and I believe that Tcl_InitStubs should 
always rely on those values alone.

    actualVersion = Tcl_PkgRequireEx(interp, "Tcl", 
version, exact,
    (ClientData *) &tmp);
    if (actualVersion == NULL) {
tclStubsPtr = NULL;
return NULL;
    }

    if (tclStubsPtr->hooks) {
tclPlatStubsPtr = tclStubsPtr->hooks-
>tclPlatStubs;
tclIntStubsPtr = tclStubsPtr->hooks-
>tclIntStubs;
tclIntPlatStubsPtr = tclStubsPtr->hooks-
>tclIntPlatStubs;
    } else {
tclPlatStubsPtr = NULL;
tclIntStubsPtr = NULL;
tclIntPlatStubsPtr = NULL;
    }
    
    return actualVersion;
}

JJM

davygrvy added on 2002-10-02 22:08:23:

File Added - 32236: bug615304.c

Logged In: YES 
user_id=7549

Attached is a test console application that does what you 
describe, but I found no crashing happening.

It could be possible that you're calling a Stubs redirected 
function after the unload (or between the loading) and that 
could be the cause.  Have a look at the attachment and let 
me know if you have any follow-up concerns.

davygrvy added on 2002-10-02 13:47:50:
Logged In: YES 
user_id=7549

Tcl_Finalize() is normally used at the end of the application.  I 
see what your doing and agree it should be looked at as 
unloading the DLL (but not the app) is a like completion.

This should probably be an easy bug to fix once I get some 
free time to have a look.

Attachments: