Open Bug 1476869 Opened 2 years ago Updated 1 year ago

Console leak content document on reload

Categories

(DevTools :: Console, defect, P3)

defect

Tracking

(Not tracked)

People

(Reporter: ochameau, Unassigned)

References

(Depends on 1 open bug, Blocks 1 open bug)

Details

STR:
* open data:text/html,<script>console.log({})</script>
* open the console
* reload the page many times

Actual result:
  Memory always go up in the content process. It is only fully release when closing the toolbox.

Excpected result:
  Memory gets back to its baseline level after each reload, or at least bit after.

It is specific to the console as the following document doesn't leak:
  data:text/html,<script></script>

Also, it is specific to logging an object from the page as this doesn't leak either:
  data:text/html,<script>console.log("foo")</script>
While this also leak:
  data:text/html,<script>console.log(document)</script>

Figuring out this leak isn't easy today as most of the existing tooling is broken against the content process. I opened bug 1476867 and bug 1476670 to address that.
Given this information, the leaks is related to this actor method:
  https://searchfox.org/mozilla-central/source/devtools/server/actors/webconsole.js#1675
We must leak something out of `message`, and especially one of these `obj` objects from here:
  https://searchfox.org/mozilla-central/source/devtools/server/actors/webconsole.js#1865-1868

The leak goes away if I hack this, to ensure freeing all the object actors:
diff --git a/devtools/server/actors/webconsole.js b/devtools/server/actors/webconsole.js
index 16e8333b6bb9a..3f307280ec48d 100644
--- a/devtools/server/actors/webconsole.js
+++ b/devtools/server/actors/webconsole.js
@@ -486,6 +486,9 @@ WebConsoleActor.prototype =
       getGlobalDebugObject: () => this.globalDebugObject
     }, this.conn);
     pool.addActor(actor);
+    setTimeout(() => {
+      this.releaseActor(actor);
+    }, 1000);
     return actor.form();
   },
 
The leak seems to be a race. It doesn't seem to leak when reloading slowly. i.e. wait for the reload before doing another one.
It only leak when we keep F5 pressed and force reload to happen very quickly.
I think it is a race where the client doesn't have time to call `releaseActor` for all the created objects. Or may be it doesn't even have time to receive the message grip and acknowledge it.

It think that there is something wrong in console actor pools. It looks like there should be a pool of object per document. Then, once the document is unloaded, we could remove the pool and all its actors. BrowsingContextActor emits window-destroyed event when the document is unloaded/hidden.
I already gave this snippet, but I think it is helpful for me to repeat it here:
  const weak = Cu.getWeakReference(obj);
  setTimeout(function () {
    Cu.forceGC(); Cu.forceCC();
    Cu.forceGC(); Cu.forceCC();
    Cu.forceGC(); Cu.forceCC();
    dump("objct still alive? "+weak.get()+"\n");
  }, 3000);
This helps knowing if a given object is still alive after a bit, thus helpful identify what leaks from what isn't.
Priority: -- → P1
Moving to p3 because no activity for at least 24 weeks.
See https://github.com/mozilla/bug-handling/blob/master/policy/triage-bugzilla.md#how-do-you-triage for more information
Priority: P1 → P3
Blocks: 1553178
No longer blocks: devtools-performance
Blocks: dt-leak
No longer blocks: 1553178
You need to log in before you can comment on or make changes to this bug.