Bug 75984 - QWebView leaks memory when QObject signal is connected to javascript slot
Summary: QWebView leaks memory when QObject signal is connected to javascript slot
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit Qt (show other bugs)
Version: 528+ (Nightly build)
Hardware: PC Linux
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-01-10 12:42 PST by juha.kuikka
Modified: 2015-01-20 06:53 PST (History)
9 users (show)

See Also:


Attachments
Application that shows the problem (2.15 KB, application/x-zip-compressed)
2012-01-10 12:42 PST, juha.kuikka
no flags Details
Demonstrates signals are received by defunct JavaScript contexts (1.40 KB, application/x-bzip)
2012-03-07 20:06 PST, Rusty
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description juha.kuikka 2012-01-10 12:42:46 PST
Created attachment 121892 [details]
Application that shows the problem

Versions:
QT 4.8 (./configure -prefix /opt/qt-x86-x11-4.8.0 -debug -qvfb -nomake demos -nomake examples)
Gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
Webkit version unknown (src/3rdparty/webkit/VERSION refers to 52a11cec052aa40d3bbc06861be1177b649b4a99)

Attached is an application and two web pages. Bug.html shows the issue, nobug.html does not. The presence of the jquery makes no difference but the more javascript content the web page has the more memory is leaked.

I see application leaking memory when javascript function is connected to a QObject signal (bug.html). When the connection is not made (nobug.html) the memory is not leaked.

In the attached example application (simplest browser) a QObject (Api) is exposed to the javascript layer through frame->addToJavaScriptWindowObject().

Javascipt then connects to "thing_happened" signal of said QObject with "Api.thing_happened.connect(callback_function)".

The web page (bug.html) contains a link to itself. While clicking this link the application leaks memory image on every click. According to valgrind the memory is not _leaked_ per se, it is apparently still reachable.
Comment 1 juha.kuikka 2012-01-10 13:00:58 PST
Environment is Ubuntu 11.10 (Oneiric Ocelot).
In case it matters I have also reproduced this on QT 4.6.3, 4.6.4 and 4.7.4. In x11 and embedded builds.
Comment 2 Rusty 2012-03-07 20:04:01 PST
In Qt 4.8, the situation is even worse.  I modified your example to emit thing_happened when the page loads.  Each time you click the link, the number of alerts that pop up is increased by one.  Specifically, the first time it loads you get one alert.  The second time it loads you get two alerts!

This means that the signals aren't being detached and are keeping the old JavaScript contexts around.  Each time the signal is emitted, every old context receives the signal in addition to the current context.

I verified the leak is present in 4.6 (Ubuntu Lucid build) and 4.7 (custom build).  The above amplification of signals adds to the problem in 4.8.
Comment 3 Rusty 2012-03-07 20:06:41 PST
Created attachment 130755 [details]
Demonstrates signals are received by defunct JavaScript contexts
Comment 4 mike 2012-06-22 21:58:03 PDT
This is a nasty problem. My application tends to reload a page over and over. So, after reloading the page five times, a single fired signal would call the Javascript slot function five times, four of which with defunct Javascript contexts. It just so happened that my slot functions sometimes were used to create Flash objects which would crash the application when it was attempted in a bogus Javascript context.

I eventually worked around it by disconnecting all slots from the signals on the application side (you can't do it from the Javascript side because as far as Javascript is concerned the signal has no connection) and reconnecting them during each page load as you normally would.
Comment 5 Sunny 2012-10-31 08:27:04 PDT
(In reply to comment #1)
> Environment is Ubuntu 11.10 (Oneiric Ocelot).
> In case it matters I have also reproduced this on QT 4.6.3, 4.6.4 and 4.7.4. In x11 and embedded builds.

@Juha, We are also getting the same issue, By any chance have you resolved it?
Comment 6 Sunny 2012-10-31 09:46:59 PDT
(In reply to comment #5)
> (In reply to comment #1)
> > Environment is Ubuntu 11.10 (Oneiric Ocelot).
> > In case it matters I have also reproduced this on QT 4.6.3, 4.6.4 and 4.7.4. In x11 and embedded builds.
> 
> @Juha, We are also getting the same issue, By any chance have you resolved it?

I just solved it by using a workaround. 
Hint, Use QWebFrame::evaluateJavascript.
Comment 7 anat sarig 2013-01-28 02:41:12 PST
My C++ side performs the following before emiting a signal to JS :
evaluateJavaScript(CloseBridge())
addToJavaScriptWindowObject(myBridgeObject)
evaluateJavaScript(InitBridge())


JS CloseBridge():
myBridgeObject.mySignal.disconnect
myBridgeObject = null

JS InitBridge()
myBridgeObject.mySignal.connect(mySlot)

What I see that on every mySignal the slot mySlot is invoked and memory consumption rise high (I pass QImage in the signal).

So I guess I did not understand the work around.

Can you please elaborate ?
Thanks.
Comment 8 Robert Knight 2013-04-23 09:45:10 PDT
Confirmed with Qt 4.8 on Mac.

I can suggest a couple of possible workarounds:

 1. The connections from Qt objects to JS functions are proxied via a hidden QObject which inherits from 'JSC::Bindings::QtConnectionObject'.  Finding these objects via QObject::children() and deleting them will remove the connection.

 2. Instead of calling object.signal.connect() directly, use a wrapper which performs the connection and saves the (method, receiver) somewhere and add a document unload handler which removes these connections.

Something like: https://gist.github.com/robertknight/5445289

I haven't tested this extensively.
Comment 9 Allan Sandfeld Jensen 2015-01-20 06:53:51 PST
WebKit Qt no longer maintained here.