Background: The relationship between the various objects are quite tricky. It takes some time to think them through. Basically, to reference a Tcl_Obj, the C structure representing a Tcl object in the C Tcl interpreter, TclBlend creates a TclObject, a Java class instance using the following relationship: TclObject (tcl.lang.TclObject, Java class) <contains> CObject (tcl.lang.CObject, Java class) <contains> a pointer to Tcl_Obj CObject is a subclass of InternalObject (tcl.lang.InternalObject). InternalObject is an abstract class containing an interface so that TclObject can be used as the common interface to not only Tcl_Obj, but also other types of TclBlend objects such as ReflectObject, TclInteger, etc, all of those are subclass of InternalObject. On the C side, the C Tcl interpreter needs access to Java objects defined in TclBlend, such as ReflectObject, TclInteger, etc. TclBlend uses a Tcl_Obj implementation to wrap around any TclObject using the following relationship: Tcl_Obj (A C struct with function pointers to functions that are specifically designed to manipulate TclBlend's TclObject. Defined in javaObj.c in TclBlend.) <contains> reference/pointer to the Java TclObject It seems that you can get infinite recusive containment as in: Tcl_Object <contains> Tcl_Obj <contains> Tcl_Object <contains> Tcl_Obj <contains> ... TclBlend is smart enough to detect such attempt. When it is detected, TclBlend removes the extra level containment so that most of the time you will have either: Tcl_Object <contains> Tcl_Obj or Tcl_Obj <contains> Tcl_Object The Problem: There are 2 conditions, which taken together causes problem with the above setup in TclBlend. 1. How are the objects been cleaned up (free'ed)? Tcl_Obj needs to be cleaned up excplictly using reference counting. Tcl_Object can be implicitly cleaned up using the GC. The original implementation in TclBlend is to use the GC to implicitly clean up Tcl_Object, which in turns cleans up the Tcl_Obj using an explict reference count decrement. By transitivity, this means that the Tcl_Obj are cleaned up implicitly by the GC. There is no problem by itself. 2. Tcl_Obj can only be free'ed by the same thread that created it (due to performance benefits). This behavior is by design and does not cause any problem by itself either because Tcl programs are usually written in C/C++, which always uses explicit memory management without anything like a GC thread. Taken 1 and 2 together causes a problem. The GC thread may be freeing a Tcl_Obj that is not created by the GC thread. This produces concurrency problems in Tcl. The proposed solution is to never use the GC thread to free Tcl_Obj and always use the thread that created the Tcl_Obj to free the Tcl_Obj. See below for more analysis of the problem. You can search the maling list archive for more discussion on this under the general subject of "GC". -- Jiang Wu [EMAIL PROTECTED] ------- Start of forwarded message ------- Subject: TclBlend Ref Counting Bug (GC related) To: [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED] From: Jiang Wu <[EMAIL PROTECTED]> Cc: [EMAIL PROTECTED] Date: 08 Aug 2000 00:12:48 PDT Currently, there is a plan to make the Java GC perform some cleanup on Tcl_Obj in TclBlend. Looking at the root cause for the GC trouble, I think there is a problem with how TclBlend uses Tcl_Obj reference counting. Here is my analysis. I think if we fix the reference counting, we don't need to do anything in the GC. TclBlend does not follow the normal Tcl_Obj reference counting usage. In TclBlend, a Java TclObject is used as the handle to the underlining Tcl_Obj: TclObject CObject Tcl_Obj Both Tcl_Obj and TclObject have reference counting. However, when incrementing or decrementing the reference count on the TclObject, this incrementing or decrementing is proxied into the native Tcl_Obj. This doesn't seem correct. In addition, when a new TclObject is created to wrap around a Tcl_Obj, the reference count of the TclObject is 0, but implicitly, the reference count of Tcl_Obj is incremented by 1. This doesn't seem right either. For example, in C, a call to Tcl_GetVar2Ex(...) returns a Tcl_Obj, of which, "The ref count for the returned object is _not_ incremented to reflect the returned reference; if you want to keep a reference to the object you must increment its ref count yourself." In TclBlend, the corresponding call is "interp->getVar()", which uses Tcl_GetVar2Ex(...). However, the resulting Tcl_Obj does have its reference count incremented by 1 implicitly by TclBlend. The problem with this implicit increment of native Tcl_Obj's reference count is that someone, namely the GC thread, must decrement the reference count. This causes all sort of undesirable behaviors such as the GC thread deadlocking because Tcl_Obj's reference count can only be modified by the thread that first created the Tcl_Obj. I think we should fix the TclBlend reference counting behavior: 1. do not implicitly increment native Tcl_Obj reference count when creating a new TclObject that wraps around a Tcl_Obj 2. when incrementing or decrementing reference count on TclObject, also proxy the action into the native Tcl_Obj 3. when TclBlend code wants to keep a Tcl_Obj for the long term, the code must increment the reference count 4. the GC thread should do nothing regarding to the native Tcl_Obj 5. put an assert into the TclObject.finalize() to catch cases when the reference count is not decremented to 0 6. do not pass Tcl_Obj to other threads, this is not supported by Tcl anyway With this fix, I dont' think there is a need to make the GC free Tcl_Obj. -- Jiang Wu [EMAIL PROTECTED] ---------------------------------------------- [EMAIL PROTECTED] is brought to you by the Stanford Alumni Association and Critical Path. ------- End of forwarded message ------- ---------------------------------------------- [EMAIL PROTECTED] is brought to you by the Stanford Alumni Association and Critical Path. ---------------------------------------------------------------- The TclJava mailing list is sponsored by Scriptics Corporation. To subscribe: send mail to [EMAIL PROTECTED] with the word SUBSCRIBE as the subject. To unsubscribe: send mail to [EMAIL PROTECTED] with the word UNSUBSCRIBE as the subject. To send to the list, send email to '[EMAIL PROTECTED]'. An archive is available at http://www.mail-archive.com/tcljava@scriptics.com