mozilla

Compare Revisions

Common causes of memory leaks in extensions

Change Revisions

Revision 49899:

Revision 49899 by Nmaier on

Revision 49900:

Revision 49900 by Sheppy on

Title:
Common causes of memory leaks in extensions
Common causes of memory leaks in extensions
Slug:
Extensions/Common_causes_of_memory_leaks_in_extensions
Extensions/Common_causes_of_memory_leaks_in_extensions
Tags:
Extensions, Add-ons, memory
Extensions, Add-ons, memory
Content:

Revision 49899
Revision 49900
n36      A similar problem is holding onto <code>window</code> objecn36      A similar problem is holding onto {{ domxref("window") }} o
>ts or DOM nodes (such as <code>window.document</code>) for too lo>bjects or DOM nodes (such as {{ domxref("window.document") }}) fo
>ng by storing them in a JavaScript module.&nbsp; For example:>r too long by storing them in a JavaScript module.&nbsp; For exam
 >ple:
n58      For some examples found in real-world add-ons, see <a classn58      For some examples found in real-world add-ons, see {{ bug("
>="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=>712733") }}, {{ bug("725875") }}, and {{ bug("727552") }}.
>712733#c17" title="https://bugzilla.mozilla.org/show_bug.cgi?id=7 
>12733#c17">bug 712733</a>, <a class="link-https" href="https://bu 
>gzilla.mozilla.org/show_bug.cgi?id=725875" title="https://bugzill 
>a.mozilla.org/show_bug.cgi?id=725875">bug 725875</a>, and <a clas 
>s="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id 
>=727552#c3" title="https://bugzilla.mozilla.org/show_bug.cgi?id=7 
>27552#c3">bug 727552</a>. 
n64      Using&nbsp;<code>setInterval</code>/<code>setTimeout</code>n64      Using {{ domxref("window.setInterval()") }} or {{ domxref("
> can be problematic, too, when it comes to zombie compartments. C>window.setTimeout()") }} can be problematic, too, when it comes t
>onsider the following example code that could be part of your <co>o zombie compartments. Consider the following example code that c
>de>browser.xul</code> overlay:>ould be part of your <code>browser.xul</code> overlay:
n78      One would normally expect that the interval (or timer) wouln78      One would normally expect that the interval (or timer) woul
>d be destroyed as soon as the document unloads, same as event lis>d be destroyed as soon as the document unloads, same as event lis
>teners are automatically destroyed. However, while this is still >teners are automatically destroyed. However, while this is still 
>true, the <code>setInterval</code> in the example originates from>true, the {{ domxref("window.setInterval()") }} in the example or
> the outer chrome window (<code>browser.xul</code>) and not from >iginates from the outer chrome window (<code>browser.xul</code>) 
>the content window. Hence the interval will only be destroyed whe>and not from the content window. Hence the interval will only be 
>n the outer window is unloaded, i.e. when the user closes the who>destroyed when the outer window is unloaded, i.e. when the user c
>le browser window, but not when the content window unloads, i.e. >loses the whole browser window, but not when the content window u
>when the user closes the tab. The interval function in the exampl>nloads, i.e. when the user closes the tab. The interval function 
>e would still hold a reference to <code>contentDoc</code>, theref>in the example would still hold a reference to <code>contentDoc</
>ore leaking the content document and the associated window and co>code>, therefore leaking the content document and the associated 
>mpartment.>window and compartment.
79    </p>
80    <p>79    </p>
81      If your add-on makes use of long-lived timeouts or uses <co80    <p>
>de>setInterval</code>, you need to take special care to ensure yo 
>ur code won't accidentally leak content windows. Therefore, your  
>add-on should clean up such intervals and timeouts when the corre 
>sponding content document is unloaded, by adding an <code>unload< 
>/code> event listener or by similar means. Another solution would 
> be to use the <code>setInterval</code>/<code>setTimeout</code> i 
>nstances content windows provide, but there is a big drawback wit 
>h this idea: If the user disables Javascript globally or locally  
>(e.g. NoScript), then using the content window functions won't wo 
>rk. 
81      If your add-on makes use of long-lived timeouts or uses {{ 
 >domxref("window.setInterval()") }}, you need to take special care
 > to ensure your code won't accidentally leak content windows. The
 >refore, your add-on should clean up such intervals and timeouts w
 >hen the corresponding content document is unloaded, by adding an 
 ><code>unload</code> event listener or by similar means. Another s
 >olution would be to use the <code>setInterval()</code>/<code>setT
 >imeout()</code> instances content windows provide, but there is a
 > big drawback with this idea: If the user disables JavaScript glo
 >bally or locally (such as by using an add-on like NoScript), then
 > using the content window functions won't work.
n109      Extensions can be disabled and removed by user actions, butn109      Extensions can be disabled and removed by user actions, but
> it also happens when an add-on is updated. If a bootstrapped (re> it also happens when an add-on is updated. If a bootstrapped (re
>startless) extension fails to clean up event listeners when disab>startless) extension fails to clean up event listeners when disab
>led/removed, the listeners will still reference the enclosing sco>led or removed, the listeners will still reference the enclosing 
>pe — usually the <code>bootstrap.js</code> Sandbox — and therefor>scope — usually the <code>bootstrap.js</code> sandbox — and there
>e keep that scope (and its enclosing compartment) alive until the>fore keep that scope (and its enclosing compartment) alive until 
> window is unloaded. If the window in question is <code>browser.x>the window is unloaded. If the window in question is <code>browse
>ul</code> or some long-lived web app such as Gmail, the leaked co>r.xul</code> or some long-lived web app such as Gmail, the leaked
>mpartment might survive for quite some time.> compartment might survive for quite some time.
n129      <strong>Note:</strong> The <em>unload()</em> function is ann129      <strong>Note:</strong> The <code>unload()</code> function i
> <a class="link-https" href="https://github.com/Mardak/restartles>s an <a class="link-https" href="https://github.com/Mardak/restar
>s/blob/unload/bootstrap.js" title="unload() boilerplate">external>tless/blob/unload/bootstrap.js" title="unload() boilerplate">exte
> function</a> which can be added in your add-on to easily provide>rnal function</a> which can be added in your add-on to easily pro
> a way to undo changes upon unloading of your add-on or a specifi>vide a way to undo changes upon unloading of your add-on or a spe
>c part/object. It is part of <a class="link-https" href="https://>cific part/object. It is part of <a class="link-https" href="http
>github.com/Mardak/restartless/">Edward Lee's restartless boilerpl>s://github.com/Mardak/restartless/">Edward Lee's restartless boil
>ate</a>.>erplate</a>.
n135      Other than Javascript compartments, add-ons may also leak "n135      Other than JavaScript compartments, add-ons may also leak "
>things" which do not get a dedicated compartment, most commonly c>things" which do not get a dedicated compartment, most commonly c
>hrome DOM windows and Javascript code modules.>hrome DOM windows and JavaScript code modules.
n141      Holding onto event observers for too long is another problen141      Holding onto event observers for too long is another proble
>m.&nbsp; Observers that use strong references are a common cause >m.&nbsp; Observers that use strong references are a common cause 
>of leaking whole chrome windows or Javascript code modules; it is>of leaking whole chrome windows or JavaScript code modules; it is
> possible to leak content windows, too, but that is less common.> possible to leak content windows, too, but that is less common.
n159      To avoid this problem explicitly call <a href="/en/XPCOM_Inn159      To avoid this problem explicitly call {{ ifmethod("nsIObser
>terface_Reference/nsIObserverService/removeObserver" title="remov>verService", "removeObserver") }} in an unload event listener. Yo
>eObserver"><code>removeObserver</code></a> in an unload event lis>u may also specify <code>ownsWeak = true</code> in the call to {{
>tener. You may also specify <code>ownsWeak = true</code> in the c> ifmethod("nsIObserverService", "addObserver") }}, but that might
>all to <a href="/en/XPCOM_Interface_Reference/nsIObserverService/> require you to properly implement weak references as well.
>addObserver" title="addObserver"><code>addObserver</code></a>, bu 
>t that might require you to properly implement weak references as 
> well. 
n179      In Javascript code modules it recommended to also observe tn179      In JavaScript code modules it recommended to also observe t
>he <code>xpcom-shutdown</code> or <code>quit-application</code> n>he <code>xpcom-shutdown</code> or <code>quit-application</code> n
>otifications and unregister your observers from that topic:>otifications and unregister your observers from that topic:
n197      Finally, a lot of services other than <a href="/ja/XPCOM_Inn197      Finally, a lot of services other than {{ interface("nsIObse
>terface_Reference/nsIObserverService" title="nsIObserverService">>rverService") }} accept {{ interface("nsIObserver") }} parameters
><code>nsIObserverService</code></a> accept <a href="/en/XPCOM_Int> or other interfaces and will keep strong references around. Plea
>erface_Reference/nsIObserver" title="nsIObserver"><code>nsIObserv>se see the corresponding documentation of these services on how t
>er</code></a> parameters or other interfaces and will keep strong>o properly unregister/remove your observers and components during
> references around. Please see the corresponding documentation of> unload.
> these services on how to properly unregister/remove your observe 
>rs and components during unload. 
198    </p>
199    <h3>198    </p>
199    <h3>
200      Forgetting to unload Javascript modules in restartless add-200      Forgetting to unload JavaScript modules in restartless add-
>ons>ons
t209      The following example shows how to unload your modules agait209      The following example shows how to unload your modules agai
>n (bootstrap.js):>n (<code>bootstrap.js</code>):

Back to History