Closed Bug 1195689 Opened 9 years ago Closed 7 years ago

e10s Can't unload module in frame script on shutdown

Categories

(Core :: XPConnect, defect, P4)

43 Branch
defect

Tracking

()

RESOLVED INCOMPLETE
Tracking Status
e10s + ---

People

(Reporter: 4b.69.6d.6f, Unassigned, NeedInfo)

References

Details

(Whiteboard: triaged)

Attachments

(1 file)

User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 YaBrowser/15.7.2357.2700 Safari/537.36

Steps to reproduce:

0. In a bootstrapped extension add global framescript to startup function: mm.loadFrameScript(pathToFrameScript, true);

Then add broadcast to shutdown function:
mm.broadcastAsyncMessage("myextension::unload", {});

Then in a frame script call Cu.import(pathToModule, localObject) and subscribe to "myextension::unload":

function onUnload()
{
  Cu.unload(pathToModule);
}
addMessageListener(myextension::unload", onUnload);

1. Open Firefox with only one tab - about:addons;
2. Install extension;
3. Wait a little;
4. Remove extension;
5. Navigate tab to about:memory.
6. Check module.


Actual results:

Module is in memory and also error message in console:

Exception... "Component returned failure code: 0x80520012 (NS_ERROR_FILE_NOT_FOUND) [nsIXPCComponents_Utils.unload]"


Expected results:

Module should be unloaded
I have same issue in the FastestTube add-on.
Blocks: e10s-addons
tracking-e10s: --- → +
Product: Firefox → Core
This is because of the asynchronous nature of those messages. By the time the content/child process receives the shutdown message, the chrome:// or resource:// url of that module has already been destroyed (as happens when disabling the add-on), so Cu.unload freaks out because it tries to unload a JSM from a location that supposedly doesn't exist.

Dave, judging from bug 481603, you seem knowledgeable in the area. Can anything be done about this? It's a big hindrance.
Status: UNCONFIRMED → NEW
Component: Untriaged → XPConnect
Ever confirmed: true
Flags: needinfo?(dtownsend)
This might be useful:
> addons.manager	ERROR	Exception calling provider XPIProvider.mapURIToAddonID:
> [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE)
> [nsIResProtocolHandler.resolveURI]"  nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)"
> location: "JS frame :: resource://gre/modules/addons/XPIProvider.jsm ::
> this.XPIProvider._resolveURIToFile :: line 2443"  data: no]
> Stack trace:
> this.XPIProvider._resolveURIToFile()@resource://gre/modules/addons/XPIProvider.jsm:2443
> < this.XPIProvider.mapURIToAddonID()@resource://gre/modules/addons/XPIProvider.jsm:4031
> < callProvider()@resource://gre/modules/AddonManager.jsm:227
> < AddonManagerInternal.mapURIToAddonID()@resource://gre/modules/AddonManager.jsm:2098
> < this.AddonManager.mapURIToAddonID()@resource://gre/modules/AddonManager.jsm:3203
> < amManager.prototype.mapURIToAddonID()@resource://gre/components/addonManager.js:65
(In reply to Luís Miguel [:quicksaver] from comment #3)
> the chrome:// or resource:// url of that module has already been destroyed

I meant to remove chrome:// from that as I have no idea if it's affected as well, haven't tested. But since JSM's are usually loaded from resource:// schemes only, it's not really relevant here.
(In reply to Luís Miguel [:quicksaver] from comment #3)
> This is because of the asynchronous nature of those messages. By the time
> the content/child process receives the shutdown message, the chrome:// or
> resource:// url of that module has already been destroyed (as happens when
> disabling the add-on), so Cu.unload freaks out because it tries to unload a
> JSM from a location that supposedly doesn't exist.

I'm not so sure about this. The message to the child to unregister the chrome and resource handlers are all async so in theory any async message you send in the shutdown functions should get there first and so the listener should still see the registrations intact.

But I don't have a lot of time available to investigate right now. If the registrations really have gone away then your best bet is to instead load the module from a file/jar url. The chrome registry or resource protocol handler can convert your current url to something real in the filesystem and if you import/unload that you shouldn't hit problems with registrations having gone away.
Flags: needinfo?(dtownsend)
I don't think anything other than chrome:// or resource:// works for JavaScript modules. Our solution was using process scripts instead of loading a JavaScript module from a frame script - the point was merely getting one execution context per process, modularization was implemented by other means (namely https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/_loader). Had the positive side-effect of reducing overhead, only supported starting with Firefox 38 however.
does the suggestion in comment 7 solve the issue?  there was no specific add-on listed, so wasn't sure who else to contact....
Flags: needinfo?(4b.69.6d.6f)
Priority: -- → P4
Whiteboard: triaged
With Firefox 57 only WebExtensions are permitted and are, by default, e10s compatible.
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: