Index: generic/nsf.c =================================================================== diff -u -r618e2ee5017eb139591870f9f521b971bb16bbc2 -r20cf684ddc5e9c54159e1b2d591b4eddccaa661d --- generic/nsf.c (.../nsf.c) (revision 618e2ee5017eb139591870f9f521b971bb16bbc2) +++ generic/nsf.c (.../nsf.c) (revision 20cf684ddc5e9c54159e1b2d591b4eddccaa661d) @@ -23204,16 +23204,36 @@ entry; lastEntry = entry, entry = entry->nextPtr) { NsfObject *object = (NsfObject *)entry->clorobj; + + if (Tcl_Command_flags(entry->cmdPtr) & CMD_IS_DELETED) { + /* + * This is a stale entry, since the cmd in the entry was already + * deleted. This might happen with duplicates in instances. We drop + * the entry from the list. + */ + if (entry == *instances) { + *instances = entry->nextPtr; + CmdListDeleteCmdListEntry(entry, NULL); + entry = *instances; + } else { + lastEntry->nextPtr = entry->nextPtr; + CmdListDeleteCmdListEntry(entry, NULL); + entry = lastEntry; + } + continue; + } if (object && !NsfObjectIsClass(object) && !ObjectHasChildren(object)) { - /*if (object->id) { - fprintf(stderr, " ... delete object %s %p, class=%s id %p ns %p\n", key, object, - ClassName(object->cl), object->id, object->nsPtr); - }*/ + /*fprintf(stderr, "check %p obj->flags %.6x cmd %p deleted %d\n", + object, object->flags, entry->cmdPtr, + Tcl_Command_flags(entry->cmdPtr) & CMD_IS_DELETED); */ + assert(object->id); + /*fprintf(stderr, " ... delete object %s %p, class=%s id %p ns %p\n", + ObjectName(object), object, + ClassName(object->cl), object->id, object->nsPtr);*/ + FreeUnsetTraceVariable(interp, object); - if (object->id) { - FinalObjectDeletion(interp, object); - } + FinalObjectDeletion(interp, object); if (entry == *instances) { *instances = entry->nextPtr; @@ -23254,11 +23274,10 @@ && !IsBaseClass(cl) ) { /*fprintf(stderr, " ... delete class %s %p\n", ClassName(cl), cl); */ + assert(cl->object.id); FreeUnsetTraceVariable(interp, &cl->object); - if (cl->object.id) { - FinalObjectDeletion(interp, &cl->object); - } + FinalObjectDeletion(interp, &cl->object); if (entry == *instances) { *instances = entry->nextPtr;