View Issue Details

IDProjectCategoryView StatusLast Update
0000412LDMud 3.3Efunspublic2018-01-29 22:57
ReporterGnomi Assigned Tolars 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Platformi686OSDebian GNU/LinuxOS Version3.1
Product Version3.3 
Fixed in Version3.3 
Summary0000412: symbol_function leaks an object reference
DescriptionHi,

the following object stays with two references in the destructed object list
(one reference for the list, one leaked):

void create()
{
    closure cl = symbol_function("create", this_object());
    destruct(this_object());
}

That's because symbol_function doesn't release the reference for the object from the stack (or the object it found by name). For each pointer to the object in the new closure, the reference count will be incremented, so that the original reference isn't used afterwards.

There has to be at least on other efun or operator that leaks a reference count, because after I fixed this I still get object (but less than before) with more than one reference, so that they stay in the destructed object list. (I advised the driver to do a cleanup_all_objects every second.) It's hard to track down these, because CHECK_OBJECT_REF isn't complaining and the DEBUG-output from (de)ref_object is simply overwhelming for a normal object. But I have objects, that have four added references from closure_init_lambda (closure.c 1044), but only two substracted references from free_closure. Is this okay or should each added reference be accompanied by a substracted reference from free_closure?

Greetings,
Gnomi

PS: These leaked references are the reason for the 95-99% CPU load we got...
TagsNo tags attached.

Activities

lars

2005-11-08 02:09

reporter   ~0000396

You are correct - it is now corrected.

This also gave me an idea for where to look for the other missing reference - turns out that when freeing a bound unbound-lambda, the free_closure() did not remove the creator object reference of the unbound-lambda.

Gnomi

2005-11-08 15:42

manager   ~0000397

There has to be at least one more leak somewhere near the closure handling.
I got a door (loaded at preload) with several leaked references. Loading and destructing the same door later didn't leak this reference. Here's the part of the debug output, that's different. The two indented 'Sub' messages are missing in the output of the first door:

Add ref to object obj/tuer#353: 35 (ass to var) interpret.c 1360
Add ref to object obj/tuer#353: 36 (lambda object) closure.c 1044
  Sub ref from object obj/tuer#353: 35 (free_svalue) interpret.c 1111
Add ref to object obj/tuer#353: 36 (previous_object) interpret.c 19435
Add ref to object obj/tuer#353: 37 (ass to var) interpret.c 1360
Add ref to object obj/tuer#353: 38 (lambda object) closure.c 1044
  Sub ref from object obj/tuer#353: 37 (free_svalue) interpret.c 1111
Add ref to object obj/tuer#353: 38 (this_object) interpret.c 16217
Add ref to object obj/tuer#353: 39 (assign_local_lvalue_no_free) interpret.c 1554
Add ref to object obj/tuer#353: 40 (assign_local_lvalue_no_free) interpret.c 1554
Sub ref from object obj/tuer#353: 39 (free_svalue) interpret.c 1111

Greetings,
Gnomi

lars

2005-11-09 10:41

reporter   ~0000398

See the added notes: replace_program_lambda_adjust() forgot to free the object references from the auxiliary lambda it created.

lars

2005-11-09 10:43

reporter   ~0000399

Es geht nur um Clones. Die erste Tuer (/obj/tuer#13), wird von
/room/church (die Kathedrale von Tadmor wir dim Preload geladen)
geclont. Wenn ich danach /room/church zerstoere, wird auch diese Tuer
zerstoert, hat aber 3 ueberfluessige Referenzen und bleibt daher ewig
in der Liste der zerstoerten Objekte. Wenn ich dann wieder /room/church
lade (und damit einen weiteren Clone - hier /obj/tuer#353 - erschaffe)
und auch wieder zerstoere, werden die Referenzen ordentlich gezaehlt.
Ich hab die Debugausgaben beider Objekte verglichen und der Unterschied
lag eben in diesen fehlenden Sub-Meldungen. (Am Ende wird das Log etwas
chaotischer, da kommen assign- und free_svalue-Meldungen in beliebiger
Reihenfolge, aber der Anfang ist bis auf diese fehlenden Zeilen gleich
und der Unterschied am Ende im Refcount entspricht genau der Anzahl
dieser fehlenden Zeilen.)

also ich kann es im HomeMUD rekonstruieren. Folgendes Programm bewirkt das
auch:

inherit "/i/tools/update_actions";
// Doesn't matter, something to inherit from.

void create()
{
    replace_program();
    lambda(0,0);
    destruct(this_object());
}

Beim replace_program wird fuer jede geschuetzte Lambda noch eine generiert.
Diese erhaelt damit auch wieder eine Referenz auf das Objekt. Dann kopiert
er die Daten von der neuen Lambda auf die alte Lambda und zerstoert
anschliessend die neue Lambda mit einem xfree, also ohne die zugehoerige
Referenz freizugeben.

Issue History

Date Modified Username Field Change
2005-11-07 18:37 Gnomi New Issue
2005-11-08 02:08 lars Status new => resolved
2005-11-08 02:08 lars Fixed in Version => 3.3
2005-11-08 02:09 lars Resolution open => fixed
2005-11-08 02:09 lars Assigned To => lars
2005-11-08 02:09 lars Note Added: 0000396
2005-11-08 15:42 Gnomi Status resolved => feedback
2005-11-08 15:42 Gnomi Resolution fixed => reopened
2005-11-08 15:42 Gnomi Note Added: 0000397
2005-11-09 10:41 lars Status feedback => resolved
2005-11-09 10:41 lars Resolution reopened => fixed
2005-11-09 10:41 lars Note Added: 0000398
2005-11-09 10:43 lars Note Added: 0000399
2006-02-28 21:05 lars Status resolved => closed
2010-11-16 10:42 lars Source_changeset_attached => ldmud.git master 84b23cbb
2010-11-16 10:42 lars Source_changeset_attached => ldmud.git master 1a7da5b1
2018-01-29 19:59 lars Source_changeset_attached => ldmud.git master 84b23cbb
2018-01-29 19:59 lars Source_changeset_attached => ldmud.git master 1a7da5b1
2018-01-29 22:57 lars Source_changeset_attached => ldmud.git master 84b23cbb
2018-01-29 22:57 lars Source_changeset_attached => ldmud.git master 1a7da5b1