Tcl Source Code

View Ticket
Login
Ticket UUID: 555058
Title: Tcl initialization fails in external app
Type: Bug Version: obsolete: 8.4a4
Submitter: rfranke Created on: 2002-05-12 09:22:58
Subsystem: 38. Init - Library - Autoload Assigned To: andreas_kupries
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2002-07-09 09:44:53
Resolution: None Closed By: davygrvy
    Closed on: 2002-07-09 02:44:53
Description:
OS Platform: Windows 2000 / MinGW or Active State Tcl

The aim is to load Tcl dynamically into a non-Tcl 
application, e.g. as Tcl is used as command language 
in a component, but not in the complete application. 

This means that Tcl_Main can not be called for the 
initialization of Tcl. Until version 8.3, one could 
create a Tcl_Interp and use it locally in the library.

However, Tcl 8.4a4 crashes with a segmentation 
violation when evaluating some built-in commands, 
e.g. "file" and "source".

Please see the little example program attachted to 
this report, which is working with Tcl 8.0 and Tcl 
8.3, but not with Tcl 8.4.

How can one use Tcl without Tcl_Main?
How is this problem solved in the Tcl Plugin?
(this bug report might be related to 540226: encoding 
init in dynamic loaded Tcl)
User Comments: davygrvy added on 2002-07-09 09:44:53:
Logged In: YES 
user_id=7549

On behalf of Andreas, I'll close this.  Yes, Tcl initialization 
has changed since 8.0, but is documented and I woudn't 
consider this a bug, just a change in behavior.

davygrvy added on 2002-06-03 04:20:21:
Logged In: YES 
user_id=7549

>How can one use Tcl without Tcl_Main?

Call Tcl_FindExecutable() to set the library path, thus where 
the encoding files are prior to the first Tcl_Init().

>How is this problem solved in the Tcl Plugin?

Umm, no development work has been done to the plugin for 
at least 2 years now, AFAIK.  It's way out-of-date.  Please 
don't refer to it as a reference point.  It's misuse of the event 
loop and thread contexts are bad enough as it is.

Without knowing argv[0], at least on windows, can be derived 
with:

char app[MAX_PATH];

GetModuleFile(GetModuleHandle(NULL), app, MAX_PATH);
Tcl_FindExecutable(app);

The first "crash" listed in the test source is not a crash.  
Tcl_Init() returns TCL_ERROR and the result is set with the 
error message.  The second might be be worth digging into, 
but for how the logic of initialisation is at this moment, today, 
calling Tcl_FindExecutable() before Tcl_Init() is the correct 
way to do it.

To have Tcl_Init call Tcl_FindExecutable on it's own would 
require argv[0], or the derivation of it.

dgp added on 2002-06-01 07:05:39:
Logged In: YES 
user_id=80530

I can't reproduce the crash on Linux.  Assigning
to someone more able to do testing on Win2K.
Again, the problem is a crash when Tcl_FindExecutable
has not been called.  Right fix is to add that call,
but can we change the crash into an error message?

davygrvy added on 2002-05-28 13:45:55:
Logged In: YES 
user_id=7549

Also note that you need to use writable strings for the script 
arguement to Tcl_Eval().

  /* call the command */
  if (Tcl_Eval(interp, "MyCmd") != TCL_OK) {

During the parsing phase, Tcl can (could need to) write 
NULLs to the string.

rfranke added on 2002-05-15 00:36:05:
Logged In: YES 
user_id=155217

Sorry for having used the wrong Tcl sources for generating 
the stack trace. Though the trace I have attached should 
still give a rough idea. And as the problem is already 
located, i.e. missing call to Tcl_FindExecutable, you might 
be able to reproduce the error with any version. 

If you say that the missing call to that function is the 
most common error when embedding Tcl, couldn't then at 
least a check be introduced before the crash and the 
calling function, e.g. Tcl_Init, return an according error?

andreas_kupries added on 2002-05-14 01:11:54:
Logged In: YES 
user_id=75003

My apologies ... I forgot to read the other comments before 
responding to the latest comment about the encoding system 
not initialized.

dgp added on 2002-05-14 01:07:35:
Logged In: YES 
user_id=80530

Yes, we've already established that a
Tcl_FindExecutable solves this problem.

Even without a Tcl_FindExecutable() call,
though, Tcl should not crash.  Maybe it will
not work properly, but it should not crash.

Locating the crash might convert it into
a good error message.

andreas_kupries added on 2002-05-14 00:07:35:
Logged In: YES 
user_id=75003

Query: Do you use "Tcl_FindExecutable" ? Failure to call 
this function is the most common error when it comes to 
embeding newer Tcl's into an application.

See also http://wiki.tcl.tk/1315.html
or http://wiki.tcl.tk/Tcl_FindExecutable*
( The * is part of the url)

vincentdarley added on 2002-05-13 23:54:15:
Logged In: YES 
user_id=32170

Unfortunately, these stack traces appear to be for non-cvs-
head of Tcl, so it's not possible to work out what line 
1920 of tclWinFCmd.c is.  Could you perhaps add some 
context?  The problem is almost certainly caused by the 
encodings subsystem not being initialised.

rfranke added on 2002-05-13 03:11:30:
Logged In: YES 
user_id=155217

You are right, it works with Tcl_FindExecutable;
Thanks a lot for this fast help!

Here is the MSVC call stack for failed Tcl_Init:

00000000()
TclpObjNormalizePath(Tcl_Interp * 0x00000000, Tcl_Obj * 
0x007d3c98, int 0) line 1920 + 25 bytes
TclNormalizeToUniquePath(Tcl_Interp * 0x00000000, Tcl_Obj * 
0x007d3c98) line 980 + 15 bytes
FSNormalizeAbsolutePath(Tcl_Interp * 0x00000000, Tcl_Obj * 
0x007d3d58) line 902 + 13 bytes
Tcl_FSGetNormalizedPath(Tcl_Interp * 0x00000000, Tcl_Obj * 
0x007d3d70) line 3982 + 13 bytes
Tcl_FSGetFileSystemForPath(Tcl_Obj * 0x007d3d70) line 4497 
+ 11 bytes
Tcl_FSAccess(Tcl_Obj * 0x007d3d70, int 0) line 1551 + 9 
bytes
CheckAccess(Tcl_Interp * 0x007a5208, Tcl_Obj * 0x007d3d70, 
int 0) line 1321 + 13 bytes
Tcl_FileObjCmd(int * 0x00000000, Tcl_Interp * 0x007a5208, 
int 3, Tcl_Obj * const * 0x007a5fd0) line 905 + 18 bytes
TclEvalObjvInternal(Tcl_Interp * 0x007a5208, int 3, Tcl_Obj 
* const * 0x007a5fd0, char * 0x00000000, int 0, int 0) line 
3030 + 25 bytes
TclExecuteByteCode(Tcl_Interp * 0x007a5208, ByteCode * 
0x007d44b0) line 1357 + 27 bytes
TclCompEvalObj(Tcl_Interp * 0x007a5208, Tcl_Obj * 
0x007a5598, int 0) line 941 + 13 bytes
Tcl_EvalObjEx(Tcl_Interp * 0x007a5208, Tcl_Obj * 
0x007a5598, int 0) line 3865 + 15 bytes
TclObjInterpProc(int * 0x007d2f20, Tcl_Interp * 0x007a5208, 
int 1, Tcl_Obj * const * 0x0012fee4) line 1074 + 21 bytes
TclEvalObjvInternal(Tcl_Interp * 0x007a5208, int 1, Tcl_Obj 
* const * 0x0012fee4, char * 0x100b10d2, int 7, int 0) line 
3030 + 25 bytes
Tcl_EvalEx(Tcl_Interp * 0x007a5208, char * 0x100b0d1c 
initScript, int 957, int 0) line 3577 + 30 bytes
Tcl_Eval(Tcl_Interp * 0x007a5208, char * 0x100b0d1c 
initScript) line 3733 + 17 bytes
Tcl_Init(Tcl_Interp * 0x007a5208) line 768 + 14 bytes
main(int 1, char * * 0x007c14b0) line 21 + 10 bytes
TCLINOTHERAPP! mainCRTStartup + 180 bytes
KERNEL32! 77e892a6()

When not calling Tcl_Init, 
then this results from Tcl_Eval(interp, "source ...")

00000000()
TclpObjNormalizePath(Tcl_Interp * 0x00000000, Tcl_Obj * 
0x007a5568, int 0) line 1920 + 25 bytes
TclNormalizeToUniquePath(Tcl_Interp * 0x00000000, Tcl_Obj * 
0x007a5568) line 980 + 15 bytes
FSNormalizeAbsolutePath(Tcl_Interp * 0x00000000, Tcl_Obj * 
0x007a5610) line 902 + 13 bytes
Tcl_FSGetCwd(Tcl_Interp * 0x00000000) line 1862 + 13 bytes
Tcl_FSGetNormalizedPath(Tcl_Interp * 0x00000000, Tcl_Obj * 
0x007a5658) line 3969 + 9 bytes
Tcl_FSGetFileSystemForPath(Tcl_Obj * 0x007a5658) line 4497 
+ 11 bytes
Tcl_FSStat(Tcl_Obj * 0x007a5658, _stati64 * 0x0012fc88) 
line 1448 + 9 bytes
Tcl_FSEvalFile(Tcl_Interp * 0x007a5208, Tcl_Obj * 
0x007a5658) line 1228 + 13 bytes
Tcl_SourceObjCmd(int * 0x00000000, Tcl_Interp * 0x007a5208, 
int 2, Tcl_Obj * const * 0x0012fef4) line 976 + 16 bytes
TclEvalObjvInternal(Tcl_Interp * 0x007a5208, int 2, Tcl_Obj 
* const * 0x0012fef4, char * 0x0040aa8c, int 20, int 0) 
line 3030 + 25 bytes
Tcl_EvalEx(Tcl_Interp * 0x007a5208, char * 0x0040aa8c, int 
20, int 0) line 3577 + 30 bytes
Tcl_Eval(Tcl_Interp * 0x007a5208, char * 0x0040aa8c) line 
3733 + 17 bytes
main(int 1, char * * 0x007c14b0) line 40 + 15 bytes
TCLINOTHERAPP! mainCRTStartup + 180 bytes
KERNEL32! 77e892a6()

dgp added on 2002-05-12 23:26:04:
Logged In: YES 
user_id=80530


Can you provide stack traces for the crashes you see?
That will help locate the problem.

I notice that your code is missing a call to
Tcl_FindExecutable() first thing in the main().
Adding that may correct the symptoms, but we should
stil locate and prevent crashes.

rfranke added on 2002-05-12 16:22:58:

File Added - 22937: TclInOtherApp.c

Attachments: