Index: generic/nsf.c =================================================================== diff -u -r51725aa434e18e9e3ce656897011c4f40c98d8dd -r16ecd9a1e7a06eb966b2d51d4a1c59457ab25d11 --- generic/nsf.c (.../nsf.c) (revision 51725aa434e18e9e3ce656897011c4f40c98d8dd) +++ generic/nsf.c (.../nsf.c) (revision 16ecd9a1e7a06eb966b2d51d4a1c59457ab25d11) @@ -1489,6 +1489,7 @@ */ static NsfObjectSystem * GetObjectSystem(NsfObject *object) { + assert(object); if (NsfObjectIsClass(object)) { return ((NsfClass *)object)->osPtr; } @@ -1524,9 +1525,10 @@ c) filters are not active on the object */ NsfObjectSystem *osPtr = GetObjectSystem(object); - Tcl_Obj *methodObj = osPtr->methods[methodIdx]; int callDirectly = 1; + Tcl_Obj *methodObj; + methodObj = osPtr->methods[methodIdx]; if (methodObj) { if ((osPtr->overloadedMethods & 1<definedMethods & 1<flags & NSF_FILTER_ORDER_VALID)) { FilterComputeDefined(interp, object); @@ -1555,8 +1557,8 @@ } #if 0 - fprintf(stderr, "CallDirectly object %s idx %s returns %s => %d\n", - objectName(object), sytemMethodOpts[methodIdx]+1, + fprintf(stderr, "CallDirectly object %s idx %d returns %s => %d\n", + objectName(object), methodIdx, methodObj ? ObjStr(methodObj) : "(null)", callDirectly); #endif /* return the methodObj in every case */ @@ -2224,11 +2226,15 @@ PrimitiveDestroy((ClientData) object); } else { if (object->teardown && !(object->flags & NSF_DESTROY_CALLED)) { - /*fprintf(stderr, " ... call destroy obj=%s flags %.4x\n", objectName(object), object->flags);*/ - - if (DispatchDestroyMethod(interp, object, 0) != TCL_OK) { - /* destroy method failed, but we have to remove the command - anyway. */ + int result = DispatchDestroyMethod(interp, object, 0); + if (result != TCL_OK) { + /*fprintf(stderr, "DispatchDestroy %p in NSDeleteChildren failed id %p teardown %p\n", + object, object->id, object->teardown);*/ + /* + * The destroy method failed. However, we have to remove + * the command anyway, since its parent is currend being + * deleted. + */ if (object->teardown) { CallStackDestroyObject(interp, object); } @@ -2733,6 +2739,7 @@ CallStackDoDestroy(Tcl_Interp *interp, NsfObject *object) { Tcl_Command oid; + /* fprintf(stderr, "CallStackDoDestroy %p flags %.6x\n", object, object->flags);*/ PRINTOBJ("CallStackDoDestroy", object); /* Don't do anything, if a recursive DURING_DELETE is for some @@ -6768,23 +6775,31 @@ /*fprintf(stderr, " DispatchDestroyMethod obj %p flags %.6x active %d\n", object, object->flags, object->activationCount); */ - + PRINTOBJ("DispatchDestroyMethod", object); /* flag, that destroy was called and invoke the method */ object->flags |= NSF_DESTROY_CALLED; - + if (CallDirectly(interp, object, NSF_o_destroy_idx, &methodObj)) { result = NsfODestroyMethod(interp, object); } else { result = CallMethod(object, interp, methodObj, 2, 0, NSF_CSC_IMMEDIATE|flags); } - + // REMOVE ME if (result != TCL_OK) { - static char cmd[] = - "puts stderr \"[self]: Error in method destroy\n\ - $::errorCode $::errorInfo\""; - Tcl_EvalEx(interp, cmd, -1, 0); + fprintf(stderr, "destroy of %p returned %d\n", object, result); + } + if (result != TCL_OK) { + /* + * The object might be already gone here, since we have no stack frame. + * Therefore, we can't even use nsf::current object safely. + */ + static char cmdString[] = + "puts stderr \"Error in method destroy\n\ + $::errorCode $::errorInfo\""; + Tcl_EvalEx(interp, cmdString, -1, 0); + if (++RUNTIME_STATE(interp)->errorCount > 20) Tcl_Panic("too many destroy errors occured. Endless loop?", NULL); } else { @@ -8754,8 +8769,8 @@ Tcl_Interp *interp; object->flags |= NSF_TCL_DELETE; - /*fprintf(stderr, "cmd dealloc %p TclDeletesObject (2d)\n", object->id, Tcl_Command_refCount(object->id)); - */ + /*fprintf(stderr, "cmd dealloc %p TclDeletesObject (%d)\n", + object->id, Tcl_Command_refCount(object->id));*/ #ifdef OBJDELETION_TRACE fprintf(stderr, "TclDeletesObject %p obj->id %p flags %.6x\n", object, object->id, object->flags); @@ -8765,6 +8780,7 @@ # ifdef OBJDELETION_TRACE fprintf(stderr, "... %p %s\n", object, objectName(object)); # endif + CallStackDestroyObject(interp, object); /*fprintf(stderr, "TclDeletesObject %p DONE\n", object);*/ } @@ -14009,7 +14025,9 @@ if ((object->flags & NSF_DESTROY_CALLED) == 0) { object->flags |= NSF_DESTROY_CALLED; + /*fprintf(stderr, "NsfODestroyMethod %p sets DESTROY_CALLED %.6x\n",object,object->flags);*/ } + object->flags |= NSF_DESTROY_CALLED_SUCCESS; if ((object->flags & NSF_DURING_DELETE) == 0) { int result; @@ -14508,9 +14526,9 @@ result = CallMethod((ClientData) cl, interp, methodObj, objc+1, nobjv+1, NSF_CM_NO_PROTECT|NSF_CSC_IMMEDIATE); } - - if (result != TCL_OK) + if (result != TCL_OK) { goto create_method_exit; + } Tcl_SetObjResult(interp, newObject->cmdName); nameObj = newObject->cmdName; @@ -14529,9 +14547,9 @@ result = CallMethod((ClientData) cl, interp, methodObj, 3, &nameObj, NSF_CSC_IMMEDIATE); } - if (result != TCL_OK) + if (result != TCL_OK) { goto create_method_exit; - + } nameObj = Tcl_GetObjResult(interp); if (GetObjectFromObj(interp, nameObj, &newObject) != TCL_OK) { @@ -14547,6 +14565,8 @@ /* in case, the object is destroyed during initialization, we incr refcount */ INCR_REF_COUNT(nameObj); result = DoObjInitialization(interp, newObject, objc, objv); + /*fprintf(stderr, "DoObjInitialization %p %s (id %p) returned %d\n", + newObject, ObjStr(nameObj), newObject->id, result);*/ DECR_REF_COUNT(nameObj); } create_method_exit: @@ -14745,6 +14765,9 @@ result = DoObjInitialization(interp, object, objc, objv); if (result == TCL_OK) { Tcl_SetObjResult(interp, object->cmdName); + } else { + // TODO remove me + fprintf(stderr, "recreate DoObjInitialization returned %d\n", result); } } return result; @@ -15835,7 +15858,7 @@ * Delete class methods; these methods might have aliases (dependencies) to * objects, which will resolved this way. */ - if (NsfObjectIsClass(object)) { + if (object && NsfObjectIsClass(object)) { for (hPtr2 = Tcl_FirstHashEntry(Tcl_Namespace_cmdTable(((NsfClass *)object)->nsPtr), &hSrch2); hPtr2; hPtr2 = Tcl_NextHashEntry(&hSrch2)) { Tcl_Command cmd = Tcl_GetHashValue(hPtr2); Index: generic/nsfInt.h =================================================================== diff -u -rd1916d543ed083b100c8f9c48dd987d92c4bdb95 -r16ecd9a1e7a06eb966b2d51d4a1c59457ab25d11 --- generic/nsfInt.h (.../nsfInt.h) (revision d1916d543ed083b100c8f9c48dd987d92c4bdb95) +++ generic/nsfInt.h (.../nsfInt.h) (revision 16ecd9a1e7a06eb966b2d51d4a1c59457ab25d11) @@ -345,6 +345,7 @@ #define NSF_IS_ROOT_CLASS 0x0100 #define NSF_TCL_DELETE 0x0200 +#define NSF_DESTROY_CALLED_SUCCESS 0x0400 /*#define NSF_CMD_NOT_FOUND 0x1000*/ #define NSF_DURING_DELETE 0x2000 #define NSF_DELETED 0x4000 Index: generic/nsfStack.c =================================================================== diff -u -r53bb8416827839e0377debd1edc299177bd6c4e6 -r16ecd9a1e7a06eb966b2d51d4a1c59457ab25d11 --- generic/nsfStack.c (.../nsfStack.c) (revision 53bb8416827839e0377debd1edc299177bd6c4e6) +++ generic/nsfStack.c (.../nsfStack.c) (revision 16ecd9a1e7a06eb966b2d51d4a1c59457ab25d11) @@ -593,12 +593,22 @@ */ object->activationCount --; - /*fprintf(stderr, "... activationCount -- (%s) --> %d\n",objectName(object), object->activationCount);*/ + /*fprintf(stderr, "... activationCount -- (%s) --> %d\n",objectName(object), + object->activationCount);*/ - /*fprintf(stderr, "decr activationCount for %s to %d cscPtr->cl %p\n", objectName(cscPtr->self), - cscPtr->self->activationCount, cscPtr->cl);*/ + /*fprintf(stderr, "decr activationCount for %s to %d object->flags %.6x dc %.6x succ %.6x\n", + objectName(cscPtr->self), cscPtr->self->activationCount, object->flags, + object->flags & NSF_DESTROY_CALLED, + object->flags & NSF_DESTROY_CALLED_SUCCESS + );*/ assert(object->activationCount > -1); - if (object->activationCount < 1 && object->flags & NSF_DESTROY_CALLED && allowDestroy) { + + // TODO remove block + if (((object->flags & NSF_DESTROY_CALLED_SUCCESS)>0) != + ((object->flags & NSF_DESTROY_CALLED)>0)) { + fprintf(stderr, "*** flags differ for obj %p\n", object); + } + if (object->activationCount < 1 && object->flags & NSF_DESTROY_CALLED_SUCCESS && allowDestroy) { CallStackDoDestroy(interp, object); } #if defined(OBJDELETION_TRACE) @@ -615,14 +625,18 @@ object = &cscPtr->cl->object; object->activationCount --; - /*fprintf(stderr, "CscFinish cl=%p %s (%d) flags %.6x cl ns=%p cmd %p cmd ns %p\n", - object, objectName(object), object->activationCount, object->flags, cscPtr->cl->nsPtr, - cscPtr->cmdPtr, ((Command *)cscPtr->cmdPtr)->nsPtr); */ - /*fprintf(stderr, "CscFinish check ac %d flags %.6x\n", - object->activationCount, object->flags & NSF_DESTROY_CALLED);*/ - - if (object->activationCount < 1 && object->flags & NSF_DESTROY_CALLED && allowDestroy) { + /*fprintf(stderr, "CscFinish check ac %d flags destroy %.6x success %.6x\n", + object->activationCount, + object->flags & NSF_DESTROY_CALLED, + object->flags & NSF_DESTROY_CALLED_SUCCESS);*/ + + // TODO remove block + if (((object->flags & NSF_DESTROY_CALLED_SUCCESS)>0) != + ((object->flags & NSF_DESTROY_CALLED)>0)) { + fprintf(stderr, "*** flags differ for class %p\n", object); + } + if (object->activationCount < 1 && object->flags & NSF_DESTROY_CALLED_SUCCESS && allowDestroy) { CallStackDoDestroy(interp, object); } #if defined(OBJDELETION_TRACE)