Bug 24458

Summary: QWebView memory leak
Product: WebKit Reporter: Benjamin Meyer <ben>
Component: WebKit QtAssignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: laszlo.gombos, manyoso, robert, yongjun.zhang
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Attachments:
Description Flags
valgrind output from the test case
none
valgrind output
none
valgrind output none

Description Benjamin Meyer 2009-03-08 23:44:58 PDT
Run the following application and watch as memory usage for the application goes up and up. :)

#include <QtGui/QtGui>
#include <QtWebKit/QtWebKit>

int main(int argc, char **argv) {
    QApplication application(argc, argv);
    while (true) {
        QWebView view;
        view.show();
    }
    return application.exec();
}
Comment 1 Benjamin Meyer 2009-03-09 00:00:54 PDT
A more valid test case:

#include <QtGui/QtGui>
#include <QtWebKit/QtWebKit>

int main(int argc, char **argv)
{
    QApplication application(argc, argv);
    
    while (true) {
        QWebView *view = new QWebView;
        view->show();
        delete view;
    }

    return application.exec();
}
Comment 2 Balazs Kelemen 2009-03-09 10:39:30 PDT
Another test case that loads the same page through one WebView in a loop.
It shows that memory usage goes up and up by WebKit itself.

#include <QWebView>
#include <QtGui>

class Loader : public QObject {
    Q_OBJECT
public:
    Loader(QWebView* view, const QUrl& url) : m_view(view), m_url(url) {}

public slots:
    void loadNext()
    {
        m_view->load(m_url);
    }
    
private:
    QWebView* m_view;
    QUrl m_url;
};

#include "main.moc"

int main(int argc, char **argv)
{
    QApplication application(argc, argv);
    QWebView view;
    QUrl url("http://www.webkit.org");
    Loader loader(&view, url);
    QObject::connect(&view, SIGNAL(loadFinished(bool)), &loader,
SLOT(loadNext()));
    view.load(url);
    view.show();

    return application.exec();
}
Comment 3 Haso Keric 2009-05-30 07:11:14 PDT
this bug makes it useless to have a Web Application run in Qt Webkit (it can only run for 1-2 hours and you have to restart it) i hope they fix this soon, someone =) that knows how to fix it.
Comment 4 Robert Hogan 2009-05-30 09:30:56 PDT
Created attachment 30804 [details]
valgrind output from the test case

valgrind output from the test case - lots of unreachable blocks created from qt
Comment 5 Robert Hogan 2009-05-30 10:08:20 PDT
Created attachment 30805 [details]
valgrind output

at icefox's suggestion added processEvents() to the testcase so that the X11 handles would get flushed:

#include <QtGui/QtGui>
#include <QtWebKit/QtWebKit>

int main(int argc, char **argv)
{
    QApplication application(argc, argv);

    for (int i=0; i < 100; i++)
     {
        QWebView *view = new QWebView;
        view->show();
        application.processEvents();
        delete view;
    }

    exit(0);
}
Comment 6 Robert Hogan 2009-05-30 13:47:25 PDT
unless i'm mistaken, adding the processEvents() to the testcase removes the memory leak. so is the original case an actual bug?
Comment 7 Robert Hogan 2009-05-30 13:51:58 PDT
Created attachment 30807 [details]
valgrind output

adding a qt quit() to the test case reduces the leaks to just a couple of X11 items. In practice memory use increases hardly at all, especially compared to the original test case.

#include <QtGui/QtGui>
#include <QtWebKit/QtWebKit>

int main(int argc, char **argv)
{
    QApplication application(argc, argv);

    for (int i=0; i < 1000; i++)
//     while (true)
     {
        QWebView *view = new QWebView;
        application.processEvents();
        view->show();
        delete view;
    }
    application.quit();
}
Comment 8 Holger Freyther 2009-05-30 20:00:00 PDT
(In reply to comment #4)
> Created an attachment (id=30804) [review]
> valgrind output from the test case
> 
> valgrind output from the test case - lots of unreachable blocks created from qt

Okay, I have used lazlos example with Plugins On/Off, WebDevelopers On/Off, Cache On/Off and I don't really see anything bad in top %MEM is not increasing, virt memory is not increasing...

Looking at the valgrind log doesn't show any obvious thing from within WebKit. E.g. it would be interesting to see how replacing QWebView with QTextEdit will keep the memleak/make it go away wih ben's example.

Comment 9 Holger Freyther 2009-05-30 20:34:46 PDT
And a good tool to see where allocations came from is memprof (get version 0.6).
Comment 10 Robert Hogan 2009-05-31 06:06:40 PDT
i ran valgrind against the case in comment #2 and the biggest culprit was plain to see! The leak is from 1000 url loads.

==16523== 11,331,196 (9,702,200 direct, 1,628,996 indirect) bytes in 8,725 blocks are definitely lost in loss record 421 of 421
==16523==    at 0x40269EE: operator new(unsigned int) (vg_replace_malloc.c:224)
==16523==    by 0x474FCD3: WebCore::FontFallbackList::fontDataAt(WebCore::Font const*, unsigned int) const (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x45EE0F0: WebCore::Font::cachePrimaryFont() const (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x45EE137: WebCore::Font::ascent() const (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x46A1B01: WebCore::RenderListMarker::calcPrefWidths() (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x469E550: WebCore::RenderListItem::updateMarkerLocation() (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x469E611: WebCore::RenderListItem::calcPrefWidths() (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x466BEFA: WebCore::RenderBox::minPrefWidth() const (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x46598CD: WebCore::RenderBlock::calcBlockPrefWidths() (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x4665859: WebCore::RenderBlock::calcPrefWidths() (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x466BEFA: WebCore::RenderBox::minPrefWidth() const (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==    by 0x46598CD: WebCore::RenderBlock::calcBlockPrefWidths() (in /home/robert/qtsdk-2009.01/qt/lib/libQtWebKit.so.4.5.0)
==16523==
==16523== LEAK SUMMARY:
==16523==    definitely lost: 9,706,770 bytes in 8,752 blocks.
==16523==    indirectly lost: 2,240,423 bytes in 19,186 blocks.
==16523==      possibly lost: 117,083 bytes in 88 blocks.
==16523==    still reachable: 2,951,274 bytes in 18,305 blocks.
==16523==         suppressed: 0 bytes in 0 blocks.
Comment 11 Benjamin Meyer 2009-06-01 09:08:16 PDT
As shown the first few examples were not valid.  The only valid example of a memory leak has been fixed (the font leak)  If there is another leak and a reproducible case is found another bug can be opened.  For those who are waiting for the leak fix it will be in Qt 4.5.2.