diff options
author | Steve Bennett <steveb@workware.net.au> | 2012-03-13 11:12:00 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2012-03-13 11:58:33 +1000 |
commit | 50d6304037f9d77c96c2ddecc4bfacf3fa289f84 (patch) | |
tree | 95313708ab24b66b57d9f66d513f3bf06a698ed3 | |
parent | b6c95fe34a5fa3b30e1f3f2fd3dc43be5414460a (diff) | |
download | jimtcl-50d6304037f9d77c96c2ddecc4bfacf3fa289f84.zip jimtcl-50d6304037f9d77c96c2ddecc4bfacf3fa289f84.tar.gz jimtcl-50d6304037f9d77c96c2ddecc4bfacf3fa289f84.tar.bz2 |
Fix a reference counting bug
Ensure that the internal rep of interp->emptyObj is never
changed to a script, since scripts use emptyObj as the source
filename when no source info is available. Instead use a special
nullScriptObj for this purpose.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r-- | jim.c | 14 | ||||
-rw-r--r-- | jim.h | 1 | ||||
-rw-r--r-- | regtest.tcl | 6 |
3 files changed, 17 insertions, 4 deletions
@@ -2994,7 +2994,7 @@ void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) { - dupPtr->internalRep = srcPtr->internalRep; + dupPtr->internalRep.sourceValue = srcPtr->internalRep.sourceValue; Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj); } @@ -3002,7 +3002,7 @@ static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *fileNameObj, int lineNumber) { JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); - JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typePtr != NULL")); + JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object")); Jim_IncrRefCount(fileNameObj); objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; objPtr->internalRep.sourceValue.lineNumber = lineNumber; @@ -3499,9 +3499,12 @@ static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct J ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr) { - struct ScriptObj *script = Jim_GetIntRepPtr(objPtr); + if (objPtr == interp->emptyObj) { + /* Avoid converting emptyObj to a script. use nullScriptObj instead. */ + objPtr = interp->nullScriptObj; + } - if (objPtr->typePtr != &scriptObjType || script->substFlags) { + if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { SetScriptFromAny(interp, objPtr, NULL); } return (ScriptObj *) Jim_GetIntRepPtr(objPtr); @@ -5256,12 +5259,14 @@ Jim_Interp *Jim_CreateInterp(void) i->unknown = Jim_NewStringObj(i, "unknown", -1); i->errorProc = i->emptyObj; i->currentScriptObj = Jim_NewEmptyStringObj(i); + i->nullScriptObj = Jim_NewEmptyStringObj(i); Jim_IncrRefCount(i->emptyObj); Jim_IncrRefCount(i->errorFileNameObj); Jim_IncrRefCount(i->result); Jim_IncrRefCount(i->stackTrace); Jim_IncrRefCount(i->unknown); Jim_IncrRefCount(i->currentScriptObj); + Jim_IncrRefCount(i->nullScriptObj); Jim_IncrRefCount(i->errorProc); Jim_IncrRefCount(i->trueObj); Jim_IncrRefCount(i->falseObj); @@ -5295,6 +5300,7 @@ void Jim_FreeInterp(Jim_Interp *i) Jim_DecrRefCount(i, i->unknown); Jim_DecrRefCount(i, i->errorFileNameObj); Jim_DecrRefCount(i, i->currentScriptObj); + Jim_DecrRefCount(i, i->nullScriptObj); Jim_FreeHashTable(&i->commands); #ifdef JIM_REFERENCES Jim_FreeHashTable(&i->references); @@ -540,6 +540,7 @@ typedef struct Jim_Interp { Jim_Obj *liveList; /* Linked list of all the live objects. */ Jim_Obj *freeList; /* Linked list of all the unused objects. */ Jim_Obj *currentScriptObj; /* Script currently in execution. */ + Jim_Obj *nullScriptObj; /* script representation of an empty string */ Jim_Obj *emptyObj; /* Shared empty string object. */ Jim_Obj *trueObj; /* Shared true int object. */ Jim_Obj *falseObj; /* Shared false int object. */ diff --git a/regtest.tcl b/regtest.tcl index d144152..2f09700 100644 --- a/regtest.tcl +++ b/regtest.tcl @@ -204,6 +204,12 @@ catch { } puts "TEST 28 PASSED" +# REGTEST 29 +# Reference counting problem at exit +set x [lindex {} 0] +info source $x +eval $x + # TAKE THE FOLLOWING puts AS LAST LINE puts "--- ALL TESTS PASSED ---" |