Conversation
Synchronous requests will have emitted the finished signal by the time we connect to it.
Unfortunately it still does not work for me. webkit_debug gives me the following output:
Sometimes in the last line I have Here is how my Gemfile.lock looks: https://gist.github.com/985d54f7eb2558f453a9 |
Thanks for your feedback. I think there's still a possible race condition here. Do you happen to be doing anything that could be opening a new window? |
I don't think so, the race condition by definition is sth unpredictable. |
FYI: we experienced the issue that Capybara hangs unexpectedly after a multipart fileupload and a page refresh, using some nifty javascript. This actually fixes our issue, so great work, thanks. |
@@ -51,7 +49,18 @@ void WebPageManager::emitLoadStarted() { | |||
|
|||
void WebPageManager::requestCreated(QByteArray &url, QNetworkReply *reply) { | |||
logger() << "Started request to" << url; | |||
m_started += reply; | |||
if (reply->isFinished()) |
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 there a race condition here? Is it possible that we get a false
from this method and then it finishes before we call connect
below? It's not clear to me how much of the reply behavior is asynchronous.
Another way to handle this would be to remove finished replies when we get the page load signal. Currently, the logic is "are there any replies left;" we can change that to "are there any unfinished replies left."
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.
I think that's a possibility. We've used this pattern elsewhere, so I went with it.
I believe the reply in progress logic was added for multi-window sync. However, it probably makes more sense to check whether there are any windows loading instead of any replies, since the pageLoading signal is more reliable. This would probably resolve the other deadlocks as well.
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.
I originally changed this to check replies for a few reasons:
- Multi-window sync
- iframes
- It now waits for dependent assets, including JavaScript
Unfortunately, the pageLoading
signal is just differently reliable; for example, you'll get multiple signals for a page with iframes, and the number of start signals doesn't always equal the number of finished signals. I think we're going to need to deduce the actual page state based on a combination of reply and page signals. That's sort of what we're doing now, but there are clearly holes in the existing logic.
Let's merge what you have; we can change the way we handle replies in a later commit if we need to. The UnsupportedContent changes are nice, and this at least reduces the possibility of a deadlock.
Related: I'd like to build up a suite of tests that reproduce these kinds of issues, similar to the malloc_spec
we used for finding the segfault in 4.8. That way, we have tests we can run before release that reduce the possibility of reintroducing race conditions. I'll give that a shot this week.
Anyway, nice work on finding the finished signal edge case.
@lucassus, could paste the full debug output of the failing scenario? I was debugging this tonight and noticed that if some resources are requested over HTTP and others over HTTPS, WebKit seems to hang, likely for security reasons. It looks like the jquery request is hanging, but I'm not sure what else. I've not been able to come up with a failing scenario for your case. I'm not sure if @jferris has had luck; he mentioned something in one of the related issues. |
@@ -10,8 +10,7 @@ | |||
void UnsupportedContentHandler::renderNonHtmlContent() { | |||
QByteArray text = m_reply->readAll(); | |||
m_page->mainFrame()->setContent(text, QString("text/plain"), m_reply->url()); | |||
m_page->setUnsupportedContentLoaded(); | |||
m_page->networkAccessManagerFinishedReply(m_reply); | |||
m_page->unsupportedContentFinishedReply(m_reply); | |||
m_page->loadFinished(true); |
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.
If we leave the loadFinished signal connected to the page, this will happen automatically. Any reason this was disconnected?
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.
I can't remember.
We went through a few iterations with the unsupported content stuff before we got one that worked right. Issues I remember:
- Multiple loadFinished signals
- No loadFinished signals
- loadFinished signal with a
false
parameter (meaning that it failed)
I don't think there were any race conditions here, so I think you just need to get the tests passing. The commit log may know more.
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 tests pass without with the signal hooked up and the line removed. There was a bunch of rework leading up to what we have now, so it's possible that we can just leave the signal hooked up and remove the line.
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.
Okay - if we don't know why the code is there, and the tests pass, let's remove it. I don't want to have dead code slowing us down.
@jferris, we don't ever seem to get inside http://git.io/ZKtWlQ. This looks to be a relic from this refactoring: http://git.io/EmaD7A. This means we only emit I'm wondering if a simpler solution would be to catch all the loadStarted signals and only emit I also think some of the confusing behavior regarding event firing may have been resolved by http://git.io/e_NaMg. This ensures that all pending events have processed by the time we check whether or not the page is loading. |
@mhoran here is the full debug output from my hanging scenario https://gist.github.com/4218354 |
@mhoran that sounds fine to me if it works. I've definitely run into situations where the number of |
Instead of emitting loadStarted when a reply is created and pageFinished when all pending replies have finished, emit these signals when the corresponding WebPage events fire.
WebPage::setContent will cause the loadFinished signal to fire, so there's no need to call loadFinished if the signal is connected.
@lucassus, could you give the latest changes on this branch a shot? I've changed the logic to not care about whether or not all replies have finished but instead depend on whether or not the WebPage has finished loading @jferris, let me know your thoughts regarding b28452e. I'm not sure if this approach wasn't working for you before, or if I'm missing something. However, the test suite is passing reliably for me (I even ran it on Windows!) |
@mhoran it was tested on this version mhoran@5bef336 |
@mhoran I think that's worth a try. Looks good to merge. |
Synchronous requests will have emitted the finished signal by the time
we connect to it.