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
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.
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.
test case from bug description.
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
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?
Logged In: NO
That works for me... Sounds like it's a doc fix... :)
Logged In: YES
user_id=7549
I don't know if a doc fix is needed.. Seems like an edge case.
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.