Bug 75984

Summary: QWebView leaks memory when QObject signal is connected to javascript slot
Product: WebKit Reporter: juha.kuikka
Component: WebKit QtAssignee: Nobody <webkit-unassigned>
Status: RESOLVED INVALID    
Severity: Normal CC: allan.jensen, anat.sarig, cmarcelo, GICodeWarrior, hausmann, juha.kuikka, mike, robertknight, sunny
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: PC   
OS: Linux   
Attachments:
Description Flags
Application that shows the problem
none
Demonstrates signals are received by defunct JavaScript contexts none

juha.kuikka
Reported 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.
Attachments
Application that shows the problem (2.15 KB, application/x-zip-compressed)
2012-01-10 12:42 PST, juha.kuikka
no flags
Demonstrates signals are received by defunct JavaScript contexts (1.40 KB, application/x-bzip)
2012-03-07 20:06 PST, Rusty
no flags
juha.kuikka
Comment 1 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.
Rusty
Comment 2 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.
Rusty
Comment 3 2012-03-07 20:06:41 PST
Created attachment 130755 [details] Demonstrates signals are received by defunct JavaScript contexts
mike
Comment 4 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.
Sunny
Comment 5 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?
Sunny
Comment 6 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.
anat sarig
Comment 7 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.
Robert Knight
Comment 8 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.
Allan Sandfeld Jensen
Comment 9 2015-01-20 06:53:51 PST
WebKit Qt no longer maintained here.
Note You need to log in before you can comment on or make changes to this bug.