QWebView - main GUI thread stops to respond after trying to load a page



  • Hello,
    I am running few processes with qApplication:qwebview on the same machine.
    once in a while after trying to load a page, the main thread stops to respond. (only timer events continue, but the code in the main GUI thread does not).
    I am loading a page with webView.setUrl, then waiting for loadfinished and meanwhile waiting in QEventLoop to keep the browser responsive.
    It works fine most of the time but sometimes after trying to load a page the main thread stops responding (linux process goes to S state).
    Anyone has an idea how to debug this thing ?
    Thanks.



  • Citing from "this article":http://www.developer.nokia.com/Community/Wiki/How_to_wait_synchronously_for_a_Signal_in_Qt:
    [quote]QEventLoop::exec() causes the event loop to recurse, and as such, can cause application code to also recurse. Usually, this recursion is unexpected. If this approach is used often, it's possible to end up with several layers of QEventLoop::exec() which cannot continue due to recursion. [/quote]

    My guess is the extra eventloop you create may be the reason for your problems.



  • Thanks for the reply,
    I didn't understand from the article though how to solve the problem or how to workaround this problem,
    do you have any suggestions ?
    I have to wait synchronously for page loadfinished in order to continue the application, and therefore I am using QEventLoop every time I am waiting for a page to finish loading.
    Thanks.



  • The problem can be solved by not using an extra eventloop. Why do you have to wait synchronously for loadFinished anyways?

    If you can't find any other way to get your software to work without the extra eventloop, atleast that might be a point to start debugging. Maybe you can build a wrapper around QEventloop to make sure you don't create more than one extra eventloop and to make sure the eventloop ends after a certain timeout interval.

    Here's a "link to a thread":http://qt-project.org/forums/viewthread/24109/ that discussed a similar problem.



  • well, the reason I have to wait synchronously for loadFinished is this:
    I am building a web robot, that travels on a website and performs stuff there, so when I load a certain page I want to wait that it finished to load before I can do whatever I want on that page ( I need all the elements to be there for sure).
    so I have created a wait_load function that after load started I start an eventloop, also start a timer for timeout that exits the eventloop if more then 60 seconds or so passed. the other condition to exit the eventloop is that a pageload event has fired.
    the code looks like that:

    @def waitLoad(self, timeout):
    retry = 1
    max_retries = 15
    while True:
    self.timer.start(timeout * 1000)
    self.eloop.exec_()
    if self.readyState == True:
    return True
    else:#retry loading page
    retry = retry + 1
    if retry > max_retries:
    return False
    self.webView.stop()
    self.wait(5)
    self.prepareLoad()
    self.webView.reload()
    return True

    def wait(self, waittime):
    self.timer.start(waittime * 1000)
    self.eloop.exec_()

    def loadFinished(self, ok):
    self.timer.stop()
    self.eloop.exit()
    if ok:
    self.readyState = True

    def timerTimeout(self):
    self.eloop.exit()@



  • You don't need an eventloop to do that. Just connect your robots startWork function to the loadFinished signal. The timeout signal could be connected to a tryReload function or a loadNextPage function.

    I'm noticing you're using python. I'm not sure if connect for signals and slots is available there, but since it's such a crucial feature of Qt it most certainly is.



  • do you mean that I do not need an eventloop to wait for the page to finish loading ?



  • Sometimes event loop loops infinitely when using network requests (I don't know why tho). Therefore I suggest to use event loop "manually" to process events as long as you are really need to.

    @
    SomeProcess process;
    process.start();

    QEventLoop loop;

    while (process.isRunning())
    loop.processEvents();

    process.getResults();
    @



  • before I started using QEventLoop, I manualy processed events using QApplication.processEvents(), that made the same bug, GUI thread hangs...
    So I tried QEventLoop, but same bug happened.
    You think eventloop.processEvents is different ?



  • [quote author="NirBlinder" date="1371026555"]do you mean that I do not need an eventloop to wait for the page to finish loading ?[/quote]

    You don't need an extra eventloop. Your application (QApplication or QCoreApplication) already has a running eventloop, so there's no need for a second one. You don't need to wait synchronously for the signal loadFinished. Just connect to the loadFinished signal and thats it.

    Maybe I'm missing something, but from the use case you described there's no need for the extra degree of complexity you're adding with the second eventloop or the processEvent calls.



  • That is interesting , as I remember if I dump the eventloop, the webpage doesn't build itself, items are not painted at all, but maybe I am doing something wrong... ?



  • Do you call something like this anywhere in you app?
    @
    QApplication app;
    app.exec();
    @

    In what context is the QWebView running (main thread of GUI application, QProcess, ...)?



  • My application is currently running in main thread of GUI application.
    its constructor looks something like this:

    @class MyBrowser(QApplication):
    def init(self):
    super(MyBrowser, self).init(None)
    self.webView = QWebView()
    self.page = WebPage(self.webView)
    self.page.setUserAgent()
    self.webView.setPage(self.page)
    self.timer = QTimer()
    self.timer.setSingleShot(True)
    self.timer.timeout.connect(self.timerTimeout)
    self.timeoutReached = False
    self.webView.showMaximized()
    self.readyState = False
    self.webView.loadFinished.connect(self.loadFinished)
    self.eloop = QEventLoop()@

    and what I do is creating an instance of it:
    @myBrowser = MyBrowser()@
    and then something like:
    @myBrowser.load("http://www,google.com")
    myBrowser.waitLoad(60)
    myBrowser.load(someotherpage)
    myBrowser.someCustomFunction()@
    and so on...

    So I do not use
    @myBrowser.exec()@

    because there is no real user handling the browser.

    Is that understood ?
    Is that the right approach ?



  • Ah ok so thats why you have no running eventloop and thus add your own.
    Since I haven't used Qt with Python I can't really comment on that, but from the c++ perspective it seems weird. Maybe you should post a question in the "Language Bindings subsection ":http://qt-project.org/forums/viewforum/15/ of this forum.



  • Ok thank you anyway , I will try that .
    Maybe I will switch to QT with C++, I heard its more stable.

    Thank you for the help , I appreciate it.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.