-
Notifications
You must be signed in to change notification settings - Fork 92
Resolve Callback Race in ColdBootVisit #92
base: swift-3.0
Are you sure you want to change the base?
Conversation
With the change implemented in turbolinks#45, the WKNavigationDelegate on ColdBootVisit is removed when the WebViewPageLoadDelegate method webView:didLoadPageWithRestorationIdentifier: is called. This callback originates from the WKScriptMessageHandler inside Turbolinks.WebView. In production, I'm seeing cases where this method can be called *before* the webView:didFinish: callback of WKNavigationDelegate. As a result, the SessionDelegate sessionDidFinishRequest: method is never called. The behavior is indeterminate. It appears to be a race condition with no guarantee of which will execute first. Ensuring the delegate is not removed until after the webview finishes loading prevents this callback from getting dropped.
Thank-you @apbendi! This seems like a reasonable change to me. Would you mind making a PR against the master branch? @zachwaugh, any objections? |
Thanks @packagethief, after some additional testing with a patched version of our app, we're seeing this issue is not completely resolved. I don't know if the issue we're now seeing is related to this patch or not, so I suggest we hold off on any action with it until I can do some more testing. I'll let you know. |
hey @packagethief, so I've determined why my patch does not seem to resolve the issue completely. While we're no longer removing the delegate prematurely, we are still reassigning it to the session via the default implementation of the That method is:
Wow. So, the race condition remains, and if the While I've identified this issue, I'm not 100% sure what the best way to resolve it is. Again, the order of operations here appears to be indeterminate. So how do we hand off the delegate cleanly, especially when the user might override the default |
OK, so I patched this by implementing The biggest problem I see with this is that it does not resolve the issue if a developer overrides Also, I worry that this patch might allow Fixing this issue comprehensively might require some bigger refactoring. Happy to hear thoughts @packagethief and @zachwaugh. Thanks! |
friendly ping @packagethief @zachwaugh |
Hey Ben! Thanks for the reminder. I need to think about this one some more. I'm starting to question the change in #45 because I can't remember why it was necessary. If the order of operations is indeterminate, then it won't work like I intended. Does reverting that change make a difference for your case? |
Thanks @packagethief. Prior to #45, there was an implicit assumption that Turbolinks was installed and working on a cold boot when the web view finished loading. This isn't true, as Turbolinks isn't installed until the The change in #45 resolved this assumption, but did so by assuming said callback would always occur after the webview So to review:
Seems to me that ColdBootVisit needs to be refactored to wait for both of these callbacks to return before transferring the navigation delegate to the Session and sending the session delegate callbacks. |
With the change implemented in #45, the WKNavigationDelegate on
ColdBootVisit is removed when the WebViewPageLoadDelegate method
webView:didLoadPageWithRestorationIdentifier: is called. This
callback originates from the WKScriptMessageHandler inside
Turbolinks.WebView.
In production, I'm seeing cases where this
method can be called before the webView:didFinish: callback
of WKNavigationDelegate. As a result, the SessionDelegate
sessionDidFinishRequest: method is never called. The behavior
is indeterminate. It appears to be a race condition with no
guarantee of which will execute first.
Ensuring the delegate is not removed until after the webview finishes
loading prevents this callback from getting dropped.