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:
- bug615304.c [download] added by davygrvy on 2002-10-02 22:08:23. [details]