From: SourceForge.net <no...@so...> - 2006-02-21 14:45:01
|
Bugs item #579617, was opened at 2002-07-10 09:09 Message generated for change (Comment added) made by dgp You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=110894&aid=579617&group_id=10894 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: 37. Init - Library - Autoload Group: obsolete: 8.5a0 >Status: Pending >Resolution: Fixed Priority: 5 Submitted By: Jean-Claude Wippler (jcw) Assigned to: Don Porter (dgp) Summary: encodings can't be found Initial Comment: Context: tclkit, which uses the std unix/tclAppInit.c, but overrides Tcl_AppInit (using TCL_LOCAL_APPINIT). Basic logic, from my (fragmentary) understanding: std main starts does a Tcl_FindExecutable launches custom tclkit_AppInit loads a few static extensions sets up a preinit script [1] call Tcl_Init The tclkit init code is relatively small, it's at: http://www.equi4.com/metakit/viewcvs.cgi/*checkout*/ tclkit/src/kitInit.c?rev=1.9 [1] The preinit script is the one that loads TclVFS which provides scripting access to the VFS C layer in the Tcl core. ---- Observed behavior: on Unix/Linux, "encoding system" returns "identity". UNLESS the executable is run on the build machine - THEN it find the installed encodings due to the fact that it remembers (!) a static absolute path of where the tcl8.4/ area is installed. ---- The special situation in Tclkit is that it stores encoding files inside a VFS, and that it uses a bit of Tcl scripting to set things up *before* encoding files can be accessed. Therefore the first call to Tcl_FindExecutable will not be able to get encodings right - nor even a call to Tcl_SetDefaultEncodingDir - because at least one interp has to run scripts before VFS is ready. For that reason, Tclkit includes a "librarypath" command coded in C, written by Vince Darley, which gets called from Tcl as soon as the VFS mount is in place. The code for this is a few dozen lines, see: http://www.equi4.com/metakit/viewcvs.cgi/*checkout*/ tclkit/src/pwb.c?rev=1.6 The essential calls there are: TclSetLibraryPath(Tcl_NewListObj(1,&path)); TclpSetInitialEncodings(); Tcl_FindExecutable(Tcl_GetVar(interp, "argv0", TCL_GLOBAL_ONLY)); What happens, is that Tcl_FindeExecutable gets called a second time - not sure why this is needed. Any help on this issue would be greatly appreciated - I'm sort of way beyond my understanding of how things work or could be made to work... Perhaps unrelated, but worth noting, is that tclkit also has trouble when run through a symlink (this is definitely of secondary imortance to me for now). ---------------------------------------------------------------------- >Comment By: Don Porter (dgp) Date: 2006-02-21 09:44 Message: Logged In: YES user_id=80530 TIP 258 is in the HEAD. Please confirm that it resolves this bug. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2005-10-03 12:16 Message: Logged In: YES user_id=80530 TIP 258 proposes the public versions of the routines and commands mentioned in prior comments. ---------------------------------------------------------------------- Comment By: Jean-Claude Wippler (jcw) Date: 2004-12-10 18:27 Message: Logged In: YES user_id=1983 Ok, looks like TIS and TSESP could be done via a #define TCL_LOCAL_APPINIT (tclkit uses the standard tcl/unix/tclAppInit.c). The LibraryPathObjCmd change is clear (and yes, make "encoding dirs ..." a core cmd, please, so I can get rid of pwb.c altogether. FWIW, I'm removing classic Mac support from kitInit.c, the rest is 97.138% clean - only thing left, for another time, is a pesky irregularity in calling TclSetStartupScriptPath too late. Thanks for a wonderful explanation and a great leap forward in startup logic clarity! ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2004-12-10 17:35 Message: Logged In: YES user_id=80530 > Startup sequence recommendation for Tclkit > is now: > TclInitSubsystems(); > TclSetEncodingSearchPath(Tcl_NewObj()); > Tcl_Main(...) Worth noting that those changes are optional. All they would so is set Tcl's encoding search path to an empty path before the Tcl_FindExecutable() within Tcl_Main() gets called. The result is the same either way -- Tcl in Tclkit won't be able to find any *.enc files -- but it can "not find anything" faster when it doesn't have to search anything. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2004-12-10 16:29 Message: Logged In: YES user_id=80530 > Currently there are two public routines > that in turn call TclInitSubsystems, > Tcl_FindExecutable() and Tcl_CreateInterp(). > Any code making calls into the Tcl library > should be written so that its know one of these > routines has been called first. Some readers might want to know that Tcl_Main() and Tk_Main(Ex)() are on the "safe list". Each of them calls the routines above. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2004-12-10 16:24 Message: Logged In: YES user_id=80530 In Tcl 8.5a2, Tcl_FindExecutable() and its components got a substantial rewrite. The body of T_FE now clearly show the various things it does: { TclInitSubsystems(); TclpSetInitialEncodings(); TclpFindExecutable(argv0); } The TclInitSubsystems() call represents the fundamental initialization of the Tcl library. Without this call coming first, many of the routines (even public ones) of the Tcl library will fail or even crash. Currently there are two public routines that in turn call TclInitSubsystems, Tcl_FindExecutable() and Tcl_CreateInterp(). Any code making calls into the Tcl library should be written so that its know one of these routines has been called first. It may be to our advantage to make TclInitSubsystems() itself a public routine (with the name Tcl_Initialize() ?) so that the responsibilities of callers are easier to describe (call Tcl_Initialize() first; call Tcl_Finalize() when the library won't be called anymore). After TclInitSubsystems() returns, all of Tcl's public routines should be "crash safe" when called according to their documentation. TclpSetInitialEncodings makes an attempt to initialize [encoding system] according to the environment of the process. Its implementation is: { Tcl_DString encodingName; Tcl_SetSystemEncoding(NULL, TclpGetEncodingNameFromEnvironment(&encodingName)); Tcl_DStringFree(&encodingName); } TclpSetInitialEncodings() might correctly initialize [encoding system], or it might not. When it cannot, it will leave [encoding system] with the value of "identity". Tclkit will face this situation, because at the time Tcl_FindExecutable is called, the *.enc files will not be found on the encoding search path yet. We should make TclpGetEncodingNameFromEnvironment() a public routine so that callers of the Tcl library can check at any time whether the value of [encoding system] agrees with what Tcl thinks the environment expects it to be. With that routine public, Tclkit can easily repeat the [encoding system] initialization attempt after it is satisfied that a proper encoding search path is in place. Finally, TclpFindExecutable() performs the function of initializing [info nameofexecutable]. The value is stored as a ProcessGlobalValue - a new kid of struct in the Tcl library - that automatically adapts itself to any changes in [encoding system]. With Tcl 8.4, Tclkit's LibraryPathObjCmd had to make a second call to Tcl_FindExecutable to reset the proper encoding for the [info noe] value. That is no longer required, and in fact causes a problem. Startup sequence recommendation for Tclkit is now: TclInitSubsystems(); TclSetEncodingSearchPath(Tcl_NewObj()); Tcl_Main(...) and within LibraryPathObjCmd(): Tcl_DString encodingName; TclSetEncodingSearchPath(objv[1]); Tcl_SetSystemEncoding(NULL, TclpGetEncodingNameFromEnvironment(&encodingName)); Tcl_DStringFree(&encodingName); and within boot.tcl: libraryPath [file join [info library] encoding] Additional cosmetic change might be to rename [libraryPath] to [encodingPath] since that's what's really being set. Tcl should expose a script level command to allow setting of the encoding search path. That might lead to a line in boot.tcl something like: encoding dirs [file join [info library] encoding] A re-attempt to set [encoding system] would then be needed, and that might mean exposing TclpGetEncodingNameFromEnvironment at the script level as well. I think working source code changes for Tclkit 8.5a2 have been fed back now. Comments on continuing plans are invited. ---------------------------------------------------------------------- Comment By: Jean-Claude Wippler (jcw) Date: 2002-07-10 20:55 Message: Logged In: YES user_id=1983 It's more complex, I think. I need to find the exe, init all subsystems, create an interp, *and* run a script. Only then is the VFS ready to be mounted. And only after that mount can I tell Tcl where to find encoding files. One could pull out things, turn them to C code, so Tcl gets used less in the above sequence. But that seems a step back. Note also that in the end, I do get the proper encoding files known to the system. The only issue seems to be that the default encoding is not set (no longer, perhaps?). Preventing TclKit from finding encoding files outside itself (unless directed to do so) is less important, since it'll just reset the encoding path later. Then again, it seems odd that one cannot somehow prevent Tcl from doing all that. Appreciate the comments though - it's becoming a bit clearer. ---------------------------------------------------------------------- Comment By: Joe English (jenglish) Date: 2002-07-10 20:45 Message: Logged In: YES user_id=68433 Part of the problem is that Tcl_FindExecutable() does a whole lot more than just finding the executable. It also (indirectly) initializes all subsystems, sets the library path, and sets the encoding path. This presents something of a catch-22 for TclKit and similar programs: they need to find the executable to mount the VFS to set the library and encoding paths, but by the time Tcl_FindExecutable() returns these have already been set (after crawling up the filesystem looking for something that either isn't there or shouldn't be used!) We can't change Tcl_FindExecutable() (too many custom Tcl shells rely on this behaviour), but having a different routine that _only_ finds the executable would be helpful. This wouldn't even need to go in the stubs table -- it, like Tcl_Main, is only needed for application initialization. ---------------------------------------------------------------------- Comment By: Jean-Claude Wippler (jcw) Date: 2002-07-10 09:26 Message: Logged In: YES user_id=1983 Whoops, bad title description: the encodings do get loaded fine, "encoding names" gives the subset I expect. It's just that the init is not happening, "encoding system" ends up being "identity" on startup. Win32 works fine, different code path. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=110894&aid=579617&group_id=10894 |