Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clarification request: what happens when a MV3 SW is shut down before answering a message #16

Open
therealglazou opened this issue Jun 22, 2021 · 5 comments
Labels
spec clarification Needs clarification when specified topic: service worker Related to service worker background scripts

Comments

@therealglazou
Copy link

We would like to see specified in our future draft what exactly happens when a message is sent from content to a MV3 ServiceWorker but the SW is shutdown before it could reply back to the sender of the message. As far as we understand, this can happen if the SW has been alive more than 5 minutes and the fact messages are being received/pending is not interrupting that process. More specifically:

  • what happens to ports connecting content and that SW? One end of the port going down, is the port retained and can a re-instantation of the SW connect back to it?
  • what happens to messages already sent but not already replied? Do implementors have to keep a queue of emitted messages from content just in case the connection with the SW falls and the content has to re-emit the message?
  • how very precisely can the content side be notified the SW went down?
  • etc.
@dotproto
Copy link
Member

I suspect that it may be a while before we're ready to tackle specifying extension service worker (SW) behaviors in this group. In the meantime, I thought it might be helpful if I speak to Chrome's current implementation.

One of the most important things to note is that the 5 minute hard limit is a Chrome implementation detail. With respect to SW lifetimes, the SW specification defers quite a bit to the implementing browser.

2.1.1. Lifetime

The lifetime of a service worker is tied to the execution lifetime of events and not references held by service worker clients to the ServiceWorker object.

A user agent may terminate service workers at any time it:

  • Has no event to handle.
  • Detects abnormal operation: such as infinite loops and tasks exceeding imposed time limits (if any) while handling the events.

A service worker has an associated start status which can be null or a Completion. It is initially null.

A service worker is said to be running if its event loop is running.

I suspect that situations where a SW might be alive for more than 5 minutes are rare in the general web context and that as a result Chrome's current hard limit is a brute-force catch-all for runaway SWs. That said, I anticipate that this will be a more common issue for extensions and, as such, we will be interested in situations where this implementation is a practical problem for developers.

what happens to ports connecting content and that SW? One end of the port going down, is the port retained and can a re-instantation of the SW connect back to it?

Ports represent a connection between a two contexts. When one end disconnects (whether intentionally or not), that connection is severed and the other end receives an onDisconnect event. At this point the port object can be safely disposed of. SW termination is no different.

When a SW is terminated, so are the ports it had open. The port is retained only in that the other end of the connection may still hold a reference to a port instance. Reinstantiation of a SW (or simply re-calling runtime.connect()) does not reconnect ports.

what happens to messages already sent but not already replied? Do implementors have to keep a queue of emitted messages from content just in case the connection with the SW falls and the content has to re-emit the message?

If a SW receives a message but does not respond before it is terminated, the message is lost. This also applies to anydata not persisted. If your application cannot tolerate any dropped messages, then yes, you may want to consider ways to make your message passing more durable.

how very precisely can the content side be notified the SW went down?

As mentioned above, an content script port will receive an onDisconnect event there is a SW on the other end and it is terminated. Chrome does not expose a reason for the disconnect, but it is possible for extension authors to differentiate between intentional and unintentional disconnects through the use of a well known disconnect procedure. For example, before disconnecting one side could send a message signaling intent to disconnect, then call disconnect() to close the port.

@dotproto dotproto added topic: service worker Related to service worker background scripts spec clarification Needs clarification when specified labels Aug 5, 2021
@tregagnon
Copy link

To be exhaustive following Simeon's comment, Chromium has runtime.onSuspend that informs background Event Pages that they are going to be unloaded.

Unfortunately, the documentation indicates there is no guarantee the asynchronous operations will be able to complete. It's logic if the unloading take precedence, but worrisome if the extension is trying to preserve its state the a browser.storage[StorageArea].

I really think MV3 ServiceWorkers would benefit of such event. Particularly if they can be some guarantee that browser.storage[StorageArea] write operations can complete.

@tophf
Copy link

tophf commented Sep 28, 2021

We can simply open another dummy port from the original context every five minutes minus several seconds to keep the service worker alive. The fact that it's possible means that there's no point in Chrome's termination of the extension's SW, it's factually an oversight made when SW was wired to the extensions API.

@tophf
Copy link

tophf commented Sep 28, 2021

SW termination in general is not an oversight as it is regulated by the web specification, even though the exact timeouts are implementation-specific. The oversight mentioned in my comment above is about extension runtime ports that aren't a part of the web model. There's no non-destructive method (that doesn't break almost all complex extensions) to prevent an extension from re-creating such ports indefinitely, however MV3 implementation pointlessly disconnects such ports after five minutes even though this behavior doesn't achieve anything meaningful, it only annoys extension developers by necessitating an ugly kludge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
spec clarification Needs clarification when specified topic: service worker Related to service worker background scripts
Projects
None yet
Development

No branches or pull requests

4 participants