Uploaded image for project: 'Apache Cordova'
  1. Apache Cordova
  2. CB-8002

Creating a new div for every Js -> Native exec() call

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Critical
    • Resolution: Fixed
    • Affects Version/s: 3.7.0
    • Fix Version/s: 3.8.0
    • Component/s: cordova-ios
    • Labels:
    • Environment:

      Tested on multiple iOS 8.1 devices, simulators

      Description

      Since the 3.7.0 update, when cordova does a Js to Native call using exec(), somehow the underlying cordova.js is creating a "gap://ready" iframe on every call. This means that if you made 1000 native calls you'll have 1000 divs on the DOM.
      I believe this issue is of critical priority as it incurs a huge memory leak.

      Screenshot from safari inspector
      https://drive.google.com/file/d/0B94TXiq5ycp1anp6aGpTbjhPdG8/view?usp=sharing

        Issue Links

          Activity

          Hide
          abadalyan Armen Badalyan added a comment -

          Happens to me as well. Created a new project with cordova cli, cordova version 4.1.1. Added console plugin. Each console.log call adds a new "gap://ready" iframe. Tested on iPad 3, iOS 7.1.

          Show
          abadalyan Armen Badalyan added a comment - Happens to me as well. Created a new project with cordova cli, cordova version 4.1.1. Added console plugin. Each console.log call adds a new "gap://ready" iframe. Tested on iPad 3, iOS 7.1.
          Hide
          shazron Shazron Abdullah added a comment -

          See CB-7735. I contacted the patch author for comment.

          Show
          shazron Shazron Abdullah added a comment - See CB-7735 . I contacted the patch author for comment.
          Hide
          Hirbod Hirbod added a comment - - edited

          I can confirm this bug. I had a setInterval() with an console.log inside and wondered myself... More then 1000 created iframes in few minutes. But it seems not to effect memory (1mb increase) (because of "display: none" I guess)

          But this should be fixed quickly. Thanks everybody!

          Edit: correction: it has bad side-effects with memory.

          Show
          Hirbod Hirbod added a comment - - edited I can confirm this bug. I had a setInterval() with an console.log inside and wondered myself... More then 1000 created iframes in few minutes. But it seems not to effect memory (1mb increase) (because of "display: none" I guess) But this should be fixed quickly. Thanks everybody! Edit: correction: it has bad side-effects with memory.
          Hide
          agrieve Andrew Grieve added a comment -

          Almost got this figured out... Should be able to commit a fix by eod.

          Show
          agrieve Andrew Grieve added a comment - Almost got this figured out... Should be able to commit a fix by eod.
          Hide
          jira-bot ASF subversion and git services added a comment -

          Commit 227d83a122733fdf0300ffe75507a221bcef2b06 in cordova-js's branch refs/heads/master from Andrew Grieve
          [ https://git-wip-us.apache.org/repos/asf?p=cordova-js.git;h=227d83a ]

          CB-8002 CB-7735 ios: Properly address iframe bridge failing when <iframe> is removed from DOM.

          Show
          jira-bot ASF subversion and git services added a comment - Commit 227d83a122733fdf0300ffe75507a221bcef2b06 in cordova-js's branch refs/heads/master from Andrew Grieve [ https://git-wip-us.apache.org/repos/asf?p=cordova-js.git;h=227d83a ] CB-8002 CB-7735 ios: Properly address iframe bridge failing when <iframe> is removed from DOM.
          Hide
          jira-bot ASF subversion and git services added a comment -

          Commit 9e53aa9976772ea0a6861d6c451fef019d29fc65 in cordova-ios's branch refs/heads/master from Andrew Grieve
          [ https://git-wip-us.apache.org/repos/asf?p=cordova-ios.git;h=9e53aa9 ]

          CB-8002 CB-7735 Update cordova.js to include bridge fix

          Show
          jira-bot ASF subversion and git services added a comment - Commit 9e53aa9976772ea0a6861d6c451fef019d29fc65 in cordova-ios's branch refs/heads/master from Andrew Grieve [ https://git-wip-us.apache.org/repos/asf?p=cordova-ios.git;h=9e53aa9 ] CB-8002 CB-7735 Update cordova.js to include bridge fix
          Hide
          agrieve Andrew Grieve added a comment -

          Fixed in 3.8.0-dev

          See CB-7735 for more details about the fix.

          Show
          agrieve Andrew Grieve added a comment - Fixed in 3.8.0-dev See CB-7735 for more details about the fix.
          Hide
          maxpli Max Plischke added a comment -

          i am seeing this in cordova 4.1.2.

          Show
          maxpli Max Plischke added a comment - i am seeing this in cordova 4.1.2.
          Hide
          as_web Andrew Schadendorff added a comment -

          I am also having this issue on Cordova 4.1.2

          Show
          as_web Andrew Schadendorff added a comment - I am also having this issue on Cordova 4.1.2
          Hide
          shazron Shazron Abdullah added a comment -

          As mentioned the fix is in cordova ios 3.8.0 which has not been released yet - wait for that

          Show
          shazron Shazron Abdullah added a comment - As mentioned the fix is in cordova ios 3.8.0 which has not been released yet - wait for that
          Hide
          Hirbod Hirbod added a comment -

          Dear Shazron, when will 3.8.0 be released? 3.7.3 is out - don't know why this critical bug isn't incorporated yet?

          Show
          Hirbod Hirbod added a comment - Dear Shazron, when will 3.8.0 be released? 3.7.3 is out - don't know why this critical bug isn't incorporated yet?
          Hide
          ghowen Georg Howen added a comment - - edited

          I'll second Hirbod here. A new version of my app including the current Cordova released on the app store yesterday and currently my users are more or less killing me. My app uses the SQLite plugin. After a few hundred SQL updates (which happen quite frequently) we have 999+ iframes in the DOM, the iOS device runs out of memory, the database stops and we have a very unhappy user. A severe memory leak like that in a framework requires an immediate fix IMHO. I had to remove my app from the app store just now to contain the damage and I am thinking hard about going native to lessen the dependancy on third party frameworks.

          I do apprechiate the work of all contributors to OSS very much and I know very well that bugs do happen. But I feel that with this one the possible side effects have not been seen in their full potential which resulted in a too relaxed release planning for the fix.

          Please release an update asap and hopefully spare some developers a lot of headaches and very angry clients. Thank you for this and all the great work on Cordova.

          Show
          ghowen Georg Howen added a comment - - edited I'll second Hirbod here. A new version of my app including the current Cordova released on the app store yesterday and currently my users are more or less killing me. My app uses the SQLite plugin. After a few hundred SQL updates (which happen quite frequently) we have 999+ iframes in the DOM, the iOS device runs out of memory, the database stops and we have a very unhappy user. A severe memory leak like that in a framework requires an immediate fix IMHO. I had to remove my app from the app store just now to contain the damage and I am thinking hard about going native to lessen the dependancy on third party frameworks. I do apprechiate the work of all contributors to OSS very much and I know very well that bugs do happen. But I feel that with this one the possible side effects have not been seen in their full potential which resulted in a too relaxed release planning for the fix. Please release an update asap and hopefully spare some developers a lot of headaches and very angry clients. Thank you for this and all the great work on Cordova.
          Hide
          Hirbod Hirbod added a comment - - edited

          I'll have some similiar issues here. I use a native google maps plugin and every time I call the addMarker() request, a new iFrame is created in DOM. After 1000 markers, my app is crashing and dead. Please guys, at least provide some way of hotfixing.

          You just can't leave such critical bugs open since 11/Nov/14. More then 2 months. Please push a 3.7.4 including at least a hotfix for that.

          I know this is an open source project and I respect this as much as I can, donate and try to contribute as much as possible, but please, don't ignore critical bugs for that such amount of time..

          Show
          Hirbod Hirbod added a comment - - edited I'll have some similiar issues here. I use a native google maps plugin and every time I call the addMarker() request, a new iFrame is created in DOM. After 1000 markers, my app is crashing and dead. Please guys, at least provide some way of hotfixing. You just can't leave such critical bugs open since 11/Nov/14. More then 2 months. Please push a 3.7.4 including at least a hotfix for that. I know this is an open source project and I respect this as much as I can, donate and try to contribute as much as possible, but please, don't ignore critical bugs for that such amount of time..
          Hide
          shazron Shazron Abdullah added a comment -

          You can install the 3.8.0-dev version of the cordova-ios platform which includes the fix thus:

          cordova platform add ios@9e53aa9976772ea0a6861d6c451fef019d29fc65 --usegit
          

          This includes the fix in CB-8002 and CB-5706 (which should impact you minimally).

          When the final 3.8.0 is out, after updating your cordova-cli tool, just do a:

          cordova platform update ios
          
          Show
          shazron Shazron Abdullah added a comment - You can install the 3.8.0-dev version of the cordova-ios platform which includes the fix thus: cordova platform add ios@9e53aa9976772ea0a6861d6c451fef019d29fc65 --usegit This includes the fix in CB-8002 and CB-5706 (which should impact you minimally). When the final 3.8.0 is out, after updating your cordova-cli tool, just do a: cordova platform update ios
          Hide
          ghowen Georg Howen added a comment -

          Thanks for the tip Shazron. I am a bit hesitant as I am not sure what kind of new bugs I'll introduce in my app with a -dev release. Would you recommend using 3.8.0-dev in a production app?

          Show
          ghowen Georg Howen added a comment - Thanks for the tip Shazron. I am a bit hesitant as I am not sure what kind of new bugs I'll introduce in my app with a -dev release. Would you recommend using 3.8.0-dev in a production app?
          Hide
          Hirbod Hirbod added a comment -

          Seems like updateing to a dev version is not possible - only if I remove the platform iOS before.. an re-add again. Too much configuration... But as far as I can see, the dev version really just fixed the two mentioned bugs - so I assume this should be stable.

          Show
          Hirbod Hirbod added a comment - Seems like updateing to a dev version is not possible - only if I remove the platform iOS before.. an re-add again. Too much configuration... But as far as I can see, the dev version really just fixed the two mentioned bugs - so I assume this should be stable.
          Hide
          shazron Shazron Abdullah added a comment - - edited

          The dev version I mentioned contains only the two bug fixes above plus 3.7.0, if you are comfortable with that I say install it. Sorry I didn't mention (as Hirbod below found out), you will have to remove your ios platform first, then add the new ios@9e53 platform

          In the future I would plan on getting hotfixes this way, although it may only contain the currently released version plus the fix only, nothing else.

          Show
          shazron Shazron Abdullah added a comment - - edited The dev version I mentioned contains only the two bug fixes above plus 3.7.0, if you are comfortable with that I say install it. Sorry I didn't mention (as Hirbod below found out), you will have to remove your ios platform first, then add the new ios@9e53 platform In the future I would plan on getting hotfixes this way, although it may only contain the currently released version plus the fix only, nothing else.
          Hide
          ghowen Georg Howen added a comment -

          Yeah, I found that out too. But for me it was fine. The hassle about removing and readding the platform is mostly with the icons and splash screens. But so far I had to remove and readd the platform for most of the cordova updates to get things to work. So I'm kinda used to it. I am testing for two days now and things seem to be OK. Thanks again, Shazron, especially for the parameters to add the platform from git.

          Show
          ghowen Georg Howen added a comment - Yeah, I found that out too. But for me it was fine. The hassle about removing and readding the platform is mostly with the icons and splash screens. But so far I had to remove and readd the platform for most of the cordova updates to get things to work. So I'm kinda used to it. I am testing for two days now and things seem to be OK. Thanks again, Shazron, especially for the parameters to add the platform from git.
          Hide
          Hirbod Hirbod added a comment -

          Georg Howen it sounds stupid, but my hotfix I've implemented works like charm (with JS)
          $('iframe').not(':last').remove();

          As soon as my DOM reaches 999+ nodes, it freezes my app and the google maps plugin. As soon as I fire $('iframe').remove() inside console (Safari Web Inspector) - everything runs fine again. For now (till 3.8.0 is out I can upgrade without removing and readding), this fixed all my problems for me.

          Show
          Hirbod Hirbod added a comment - Georg Howen it sounds stupid, but my hotfix I've implemented works like charm (with JS) $('iframe').not(':last').remove(); As soon as my DOM reaches 999+ nodes, it freezes my app and the google maps plugin. As soon as I fire $('iframe').remove() inside console (Safari Web Inspector) - everything runs fine again. For now (till 3.8.0 is out I can upgrade without removing and readding), this fixed all my problems for me.
          Hide
          khansen Kim Hansen added a comment - - edited

          Putting in a plug for getting this fix out sooner than later. The memory growth doesn't trigger iOS memory warnings so a dev may be unaware it's happening. It does not appear as a leak in Instruments, but that's expected since it's not really a leak. In our app, it seems like the OS or the browser puts us in bad-app jail and queues up native calls.

          Symptomatically, Xcode console output stops and calls through the dialogs plugin don't result in a dialog presentation--nothing at all happens. Non system events proceed normally so until there's a failed system level call a user will think the app is ok. As soon as the home button is pressed, Xcode console will barf out all of the queued console.log messages and when the app is relaunched (without force quit), the queued dialogs appear. All of them, one at a time.

          For the benefit of google, Instruments shows unabated growth of the memory allocated to VM: JS garbage collector. My simple test method is to use setInterval to fire off a console.log message indicating the current time, and then watch the console either in Xcode itself or via the devices window in Xcode. At some point in time with 3.7.0, the console messages will stop arriving.

          I have tested the fix on the following devices, watching both for the above symptoms and for the linear memory usage expansion signature (we make routine system calls in our app) in both Instruments and Xcode. I am satisfied (enough) that the fix is production worthy, we'll be shipping to Apple later today.

          • iPhone 4S on 7.0.6
          • iPhone 5, 5S and 6 on 8.1.3
          Show
          khansen Kim Hansen added a comment - - edited Putting in a plug for getting this fix out sooner than later. The memory growth doesn't trigger iOS memory warnings so a dev may be unaware it's happening. It does not appear as a leak in Instruments, but that's expected since it's not really a leak. In our app, it seems like the OS or the browser puts us in bad-app jail and queues up native calls. Symptomatically, Xcode console output stops and calls through the dialogs plugin don't result in a dialog presentation--nothing at all happens. Non system events proceed normally so until there's a failed system level call a user will think the app is ok. As soon as the home button is pressed, Xcode console will barf out all of the queued console.log messages and when the app is relaunched (without force quit), the queued dialogs appear. All of them, one at a time. For the benefit of google, Instruments shows unabated growth of the memory allocated to VM: JS garbage collector. My simple test method is to use setInterval to fire off a console.log message indicating the current time, and then watch the console either in Xcode itself or via the devices window in Xcode. At some point in time with 3.7.0, the console messages will stop arriving. I have tested the fix on the following devices, watching both for the above symptoms and for the linear memory usage expansion signature (we make routine system calls in our app) in both Instruments and Xcode. I am satisfied (enough) that the fix is production worthy, we'll be shipping to Apple later today. iPhone 4S on 7.0.6 iPhone 5, 5S and 6 on 8.1.3
          Hide
          Hirbod Hirbod added a comment -

          Where can we find you plugin / your fix ?

          Show
          Hirbod Hirbod added a comment - Where can we find you plugin / your fix ?
          Hide
          mattstuehler Matt Stuehler added a comment -

          @Kim - would you mind sharing some advice about the fix you implemented? I was thinking about setting up an interval that would look for these iframes and remove them from the DOM, but that seems pretty inefficient. I'm also planning to try to add a function that would eliminate iframes from the DOM after each native function call, but I'm not sure about the timing (e.g., are they added to the DOM immediately after the native function call, or do I need to wait x milliseconds?) Hopefully you've come up with a more robust, reliable, and elegant solution!

          Show
          mattstuehler Matt Stuehler added a comment - @Kim - would you mind sharing some advice about the fix you implemented? I was thinking about setting up an interval that would look for these iframes and remove them from the DOM, but that seems pretty inefficient. I'm also planning to try to add a function that would eliminate iframes from the DOM after each native function call, but I'm not sure about the timing (e.g., are they added to the DOM immediately after the native function call, or do I need to wait x milliseconds?) Hopefully you've come up with a more robust, reliable, and elegant solution!
          Hide
          khansen Kim Hansen added a comment -

          The Fix for me was simply to use the 3.8.0dev version of the iOS platform. My little interval thing was just to let me see exactly when my app stopped sending console messages, as this appeared to happen at the same time that my app stopped handling calls to native code. Once I confirmed that the new iOS platform code was successful in controlling the memory growth, I took it out!

          Show
          khansen Kim Hansen added a comment - The Fix for me was simply to use the 3.8.0dev version of the iOS platform. My little interval thing was just to let me see exactly when my app stopped sending console messages, as this appeared to happen at the same time that my app stopped handling calls to native code. Once I confirmed that the new iOS platform code was successful in controlling the memory growth, I took it out!
          Hide
          rajatrocks Rajat Paharia added a comment -

          Based on the idea from Hirbod, while waiting for the official 3.8.0 release, I put this function into my app, and call it from some user-initiated actions that I know happen relatively frequently: (note that it's not totally generic as it references frameworks and variables from my app, but it's just to give you an idea).

          killZombies
                      killZombies: function() {
                          //// Temporary JS workaround until iOS Platform 3.80 is available to deal with this bug in 3.70
                          // https://issues.apache.org/jira/browse/CB-8002
                          // delete extra gap://ready iframes.
                          $ionicPlatform.ready(function() {
                              if ($rootScope.vars.isCordovaApp && angular.isDefined(device.platform) && 
                                  device.platform.toUpperCase() == "IOS") {
                                  var frames = document.getElementsByTagName("iframe");
                                  var gapFrames = [];
                                  angular.forEach(frames, function(value) {
                                      if (value.src == "gap://ready") {
                                          gapFrames.push(value);
                                      }
                                  });                    
          
                                  // delete all but the last one. 
                                  var deleteCounter = 0;
                                  var totalLength = gapFrames.length;
                                  if (gapFrames.length > 1) {
                                      for (var i = gapFrames.length -2; i >= 0; i--) {                            
                                          //console.log ("Deleting gapFrame " + i + " of " + totalLength);
                                          angular.element(gapFrames[i]).remove();                            
                                          deleteCounter++;
                                      }
                                  }
                                  console.log ("Deleted " + deleteCounter + " gapFrames");
                              }
                          });      
                      },
          
          Show
          rajatrocks Rajat Paharia added a comment - Based on the idea from Hirbod , while waiting for the official 3.8.0 release, I put this function into my app, and call it from some user-initiated actions that I know happen relatively frequently: (note that it's not totally generic as it references frameworks and variables from my app, but it's just to give you an idea). killZombies killZombies: function() { //// Temporary JS workaround until iOS Platform 3.80 is available to deal with this bug in 3.70 // https://issues.apache.org/jira/browse/CB-8002 // delete extra gap://ready iframes. $ionicPlatform.ready(function() { if ($rootScope.vars.isCordovaApp && angular.isDefined(device.platform) && device.platform.toUpperCase() == "IOS" ) { var frames = document.getElementsByTagName( "iframe" ); var gapFrames = []; angular.forEach(frames, function(value) { if (value.src == "gap: //ready" ) { gapFrames.push(value); } }); // delete all but the last one. var deleteCounter = 0; var totalLength = gapFrames.length; if (gapFrames.length > 1) { for ( var i = gapFrames.length -2; i >= 0; i--) { //console.log ( "Deleting gapFrame " + i + " of " + totalLength); angular.element(gapFrames[i]).remove(); deleteCounter++; } } console.log ( "Deleted " + deleteCounter + " gapFrames" ); } }); },

            People

            • Assignee:
              agrieve Andrew Grieve
              Reporter:
              serdaronal Serdar Onal
            • Votes:
              3 Vote for this issue
              Watchers:
              15 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development