-
Notifications
You must be signed in to change notification settings - Fork 312
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
The promises returned by skipWaiting() should have more consistent activation-waiting behavior and not call Activate() multiple times #1015
Comments
Right. It seems they obviously need to be fixed. Your suggestion would be an option here, but let me clarify two things around the desired behavior and the race condition. First, when called on a waiting worker, do we want
But I think the client already has other ways to detect the registration has an active worker that can control it such as That said, I think it'd give more consistent and expected behavior to devs if Secondly, having reviewed the steps again, Activate (currently cannot-be-queued job) and Unregister (queued job) can race on registration's waiting worker, I suppose. As far as I remember, this was previously pointed out by @wanderview. Sorry about that. I was worrying about it possibly blocking the Register/Update jobs in the job queue while waiting until no client is using the registration. However, I think it was just my confusion. It seems we can create and queue the Activate job outside the waiting condition. I wonder @wanderview still thinks it'd be right decision to make Activate a job to be queued in the job queue. If that's the case, we will probably be able to take advantage of job aggregation as well. /cc @jakearchibald |
Yes, this is a much better idea! It reduces the complexity and reduces skipWaiting() to its core. As you describe it now, I understand that the current spec just wanted to ensure activation was initiated in the case the "Install" algorithm had already completed. Currently step 24 of Install's "Wait until... registration's waiting worker's skip waiting flag is set." phrasing may cover this now? Would the skipWaiting() description just provide a pointer/reference to that? |
Yes, I think the case is covered here, but we still need to change the step 25 where Activate is invoked only when "waitingWorker’s skip waiting flag is not set". This condition has been there to avoid redundant calls to Activate as, with the current text, I think we now agree on the expected behavior. I'd like to have @jakearchibald's input before changing this though since he initially spec'd this part. (Just want to confirm what the original intention was and we're not missing any important bits.) @wanderview, also your feedback about Activate job idea would be helpful. If the implementation is just good without that change, I don't think I want to change it for now. The scenario I'm concerned about is Activate is entered and executed as waiting worker is not null, and while it's executing a queued Unregister job is scheduled, run and reaches Clear Registration interleaved with Activate. |
Test-wise, I audited the tests and found only service-workers/service-worker/skip-waiting-installed.https.html makes any assumptions about skipWaiting() providing guarantees about activation having occurred. All other uses of skipWaiting() separately wait for activation to occur. |
I agree this is the best thing to do now. I think if we did everything again, I'd prefer it if |
@asutherland, thanks for checking it! |
Before this, skipWaiting() promises when called multiple times on a waiting worker had different behaviors among each other where the winner waits unitl the Activate is complete while others don't. This makes the behavior consistent by making the Activate be called only once. To achieve that, this removes the steps in skipWaiting() that call the Activate on a waiting worker (so promise resolves right away after setting the skip waiting flag) and simplifies the call sites of the Activate in the Install algorithm. Related issue: #1015.
(This was resolved in December by the merged patch, closing.) |
According to the current spec, skipWaiting() promise should be resolved earlier even in the case that the service worker state is "installed", and then continues the activate in parallel. The test case violate that. The background is in w3c/ServiceWorker#1015. BUG=725616 Change-Id: Ic09b4d404ea41138c8bda8d3ced07094a7ebc6ab Reviewed-on: https://chromium-review.googlesource.com/571612 Cr-Commit-Position: refs/heads/master@{#487024} WPT-Export-Revision: 2256ed61b315000c27f6c8b0dd94a3f025c4adc1
According to the current spec, skipWaiting() promise should be resolved earlier even in the case that the service worker state is "installed", and then continues the activate in parallel. The test case violate that. The background is in w3c/ServiceWorker#1015. BUG=725616 Change-Id: Ic09b4d404ea41138c8bda8d3ced07094a7ebc6ab Reviewed-on: https://chromium-review.googlesource.com/571612 Cr-Commit-Position: refs/heads/master@{#487754} WPT-Export-Revision: 8d477e09e22742fee30abee882e5349ef539b5e3
According to the current spec, skipWaiting() promise should be resolved earlier even in the case that the service worker state is "installed", and then continues the activate in parallel. The test case violate that. The background is in w3c/ServiceWorker#1015. BUG=725616 Change-Id: Ic09b4d404ea41138c8bda8d3ced07094a7ebc6ab Reviewed-on: https://chromium-review.googlesource.com/571612 Commit-Queue: Xiaofeng Zhang <[email protected]> Reviewed-by: Makoto Shimazu <[email protected]> Cr-Commit-Position: refs/heads/master@{#487784} WPT-Export-Revision: b2da840104a198eaf197f0903419fc24f39aa9a6
According to the current spec, skipWaiting() promise should be resolved earlier even in the case that the service worker state is "installed", and then continues the activate in parallel. The test case violate that. The background is in w3c/ServiceWorker#1015. BUG=725616 Change-Id: Ic09b4d404ea41138c8bda8d3ced07094a7ebc6ab Reviewed-on: https://chromium-review.googlesource.com/571612 Commit-Queue: Xiaofeng Zhang <[email protected]> Reviewed-by: Makoto Shimazu <[email protected]> Cr-Commit-Position: refs/heads/master@{#487784} WPT-Export-Revision: b2da840104a198eaf197f0903419fc24f39aa9a6
The current high-level intent for ServiceWorkerGlobalScope.skipWaiting() seems to be:
event.waitUntil(self.skipWaiting())
.skip-waiting-installed.https.html
test where skipWaiting() is invoked in response to a "message" event.As specified right now, in the latter case if you call skipWaiting() twice, the first call will work as expected (set skip waiting, invoke Activate() and not resolve until Activate() fully completes). If you call it a second time, Activate() will be invoked again, aborting on step 1 ("If registration’s waiting worker is null, abort these steps.") because the previous Activate() call will have transitioned the worker to be the registration's "active worker". The promise will then resolve immediately regardless of whether the SW has activated or not.
There is also a potential variant on the second skipWaiting() call case where "Handle Service Worker Client Unload" calling Activate() races against the SW calling skipWaiting() at the request of an uncontrolled client's postMessage. If skipWaiting() wins, the promise waits for activation. If it loses, it doesn't wait.
Per discussion with @wanderview we think the core of a fix to make skipWaiting()'s promise consistent would be to:
[NewObject]
) that are waiting on activation and resolve them when the SW activates, even if it's via a different Activate() invocation.One way to do accomplish this might be to:
The text was updated successfully, but these errors were encountered: