Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
core(driver): handle promise rejections from sendCommand #6739
core(driver): handle promise rejections from sendCommand #6739
Changes from 2 commits
55165e8
c5ae03e
3d64d5d
773e4f7
ab932b4
85bda02
76a4046
b1fd5b6
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it okay to await these? The comments above them talk about racing like this might be purposefully not-awaited.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug is marked as fixed now. If it truly is, can you also remove the comments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the big bug was definitely about not awaiting
Page.navigate
, but why are we needing toawait
these? is it just about unhandled rejections?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could still timeout on any protocol command. what happens in the underlying connection dies? we should avoid any possible unhandled rejection.
But
await
each command isn't the only way to avoid unhandled rejections here. wdyt of just tacking acatch
on Page.enable, or combining the two commands like this:so that it's one less event loop iteration ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right I'm onboard with that, but I'm asking because there are then other things we might try instead of serialling awaiting like
this._sendAndSilentlyIgnoreErrors
or something :)It looks like we used to be just fine waiting on these in sequence though, and the
Page.navigate
change just moved all of 'em to be together, so we don't need to go crazy avoiding theawait
#3413I'm a tad spooked by this given that it was a real nasty bug to hunt down, but I think this makes sense if the bug really is fixed. +1 to removing the comments if we're making this change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_innerSendCommand
is specifically for when you don't want to timeout.I'm not sure if
_innerSendCommand
can ever reject. You could try setting a breakpoint just before, then kill Chrome, then hit play, and see what happens ... But if I read the code correctly for how the connection works, it won't ever result in a rejected promise - just a stalled one.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or I guesssendCommand
is never the real problem it's always the PROTOCOL_TIMEOUT that's the real problem?You guys beat me to the punch you're already on it 👍 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe I'm not following the conversation correctly here, but
_innerSendCommand
can reject viaconnection
:lighthouse/lighthouse-core/gather/connections/connection.js
Lines 120 to 124 in 9ebf069
(throwing inside
Promise.resolve().then(_ => {/* throw */})
rejects it, thencallback.resolve()
with a rejected promise rejects as well. We could probably make that a lot more understandable with an explicitcallback.resolve
orcallback.reject
, as well as using anasync
function for the inner part)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so do we want to add an empty
catch
to thethis._innerSendCommand('Page.navigate', {url});
line? Or are we assuming it's so rare that it's ok that aunhandledRejection
listener can catch it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it seems like this never happens, should we just let sleeping dragons lie?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, after talking this through for a little while, we think we do want to incorporate the
Page.navigate
errors into the promise chain. It's a little ugly, so if anyone has any other structure ideas, please chime in :)Basically it would be something like
Page.navigate
has no problem, as before it doesn't block or interfere with observing the page loadPage.navigate
throws, it wins thePromise.all
with a rejection, which leads to lighthouse exit.The main issue I see (besides reduced readability) is that we don't clean up the
_waitForFullyLoaded
machinery. This is a fatal error so it doesn't matter in most clients, but are we going to have to actually clean up to support when LH is run as a module?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also during error testing we discovered that
_waitForFrameNavigated
should probably also have a timeout instead of blindly waiting on thePage.frameNavigated
event.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WDYT about having an option to
this.once
that does the timeout bit?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why don't we just await
waitForPageNavigateCmd
as the ultimate very last thing? the only thing we want to happen is get the errors into the chain, right? if we do it as the very last thing, then it can't prevent other cleanupThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, good idea. We have at least one or two places we will happily wait forever on an event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
though the service worker one I'm thinking of only waits forever on
about:blank
, which adding an_waitForFrameNavigated
timeout will fix :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would definitely be easier to follow.
The ordering will be a little wonky (I'd imagine a
Page.navigate
failure would end up usually failing on another command within_waitForFullyLoaded
or by hitting the 45 second timeout), but ordering is already an issue withPromise.all()
(and without cancelling_waitForFullyLoaded
), and we've already all agreed thatPage.navigate
rarely if ever fails :)