ICEfaces
  1. ICEfaces
  2. ICE-8555

ice:panelPopup leaking memory when displayed and hidden

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 3.0, EE-3.0.0.GA
    • Fix Version/s: EE-3.2.0.BETA, EE-3.2.0.GA, 3.3
    • Component/s: ICE-Components
    • Labels:
      None
    • Environment:
      IE 8, Glassfish or Tomcat, any page with ice:panelPopup. Live showcase also shows issue.
    • Assignee Priority:
      P1
    • Workaround Description:
      Hide
      The simplest and quite correct workaround is to add the f:ajax or ace:ajax tag to the "Cancel" h:commandButton. This way the ICEfaces form submit is executed and ice.onElementUpdate callbacks are invoked. Also when the "Cancel" button is clicked the file upload will not proceed, this is the correct part since you don't want to upload the file but to cancel instead.
      Show
      The simplest and quite correct workaround is to add the f:ajax or ace:ajax tag to the "Cancel" h:commandButton. This way the ICEfaces form submit is executed and ice.onElementUpdate callbacks are invoked. Also when the "Cancel" button is clicked the file upload will not proceed, this is the correct part since you don't want to upload the file but to cancel instead.

      Description

      In terms of seeing a leak the showcase offers a simple test. Go to the ice:panelPopup Overview (http://icefaces-showcase.icesoft.org/showcase.jsf?grp=compatMenu&exp=popup) in IE 8. Note the starting memory, then open/close the popup 5 times.
      In my case the result looked like this:

      Initial Task Manager Memory: 32408
      Open/Close One Time: 45596
      Two: 54188
      Three: 63676
      Four: 71076
      Five: 79300
      Total Increase: 46.892mb

      If you navigate to another page in the app via the links on the left the memory will drop off. In my case clicking the panelDivider link restored the memory to 39504.

      As you can see when they AREN'T navigating this constant increase is going to be a problem.

      Similarly when looking at the page in Google Chrome you can see a huge jump in detached DOM elements. Opening the popup once and taking a Heap Snapshot revealed 11, 29, and 2019 entries. In this case the 29 entries have their Objects Count increased by 1 each time the popup is toggled again.

      Testing with the patches from ICE-8500 shows less of a leak.

      Note that a quick test using the ace:dialog demo on Showcase seems like it doesn't leak memory.
      1. FileEntryPopupTest.zip
        20 kB
        Arran Mccullough
      2. FileEntryPopupTestWAR.zip
        9.34 MB
        Arran Mccullough
      1. screenshot-01.png
        161 kB

        Activity

        Carlo Guglielmin created issue -
        Ken Fyten made changes -
        Field Original Value New Value
        Salesforce Case []
        Fix Version/s EE-3.0.0.GA_P01 [ 10327 ]
        Hide
        Ken Fyten added a comment -

        Analysis and quick-fix via configuration parameter are documented in the original JIRA: ICE-8535.

        Arturo Zambrano added a comment - 06/Sep/12 01:21 PM
        Added new parameter 'com.icesoft.faces.IE8DisableModalFrame' to determine whether to show the modal frame or not in IE8, in order to prevent this memory leak. Committed fix at revision 30711 in the maintenance branch and at revision 30712 in the trunk.

        [ Permlink | Edit | Delete | « Hide ]
        Ken Fyten added a comment - 06/Sep/12 05:39 PM
        Re-opening to see if we can solve this without a config param for 3.2 final.

        Show
        Ken Fyten added a comment - Analysis and quick-fix via configuration parameter are documented in the original JIRA: ICE-8535. Arturo Zambrano added a comment - 06/Sep/12 01:21 PM Added new parameter 'com.icesoft.faces.IE8DisableModalFrame' to determine whether to show the modal frame or not in IE8, in order to prevent this memory leak. Committed fix at revision 30711 in the maintenance branch and at revision 30712 in the trunk. [ Permlink | Edit | Delete | « Hide ] Ken Fyten added a comment - 06/Sep/12 05:39 PM Re-opening to see if we can solve this without a config param for 3.2 final.
        Hide
        Ken Fyten added a comment - - edited

        Need to understand why the modal layer causes the IE8 memory leak, perhaps we can adjust it directly and then remove the special flag.

        Show
        Ken Fyten added a comment - - edited Need to understand why the modal layer causes the IE8 memory leak, perhaps we can adjust it directly and then remove the special flag.
        Migration made changes -
        Assignee Arturo Zambrano [ artzambrano ] Ken Fyten [ ken.fyten ]
        Migration made changes -
        Assignee Ken Fyten [ ken.fyten ] yip.ng [ yip.ng ]
        Ken Fyten made changes -
        Fix Version/s 3.3 [ 10370 ]
        Fix Version/s 3.2 [ 10338 ]
        yip.ng made changes -
        Attachment screenshot-01.png [ 15091 ]
        Hide
        yip.ng added a comment -

        Cleanup supposed to be done by Ice.modal.stop(). This function existed as early as 2006. (Check-in comment was "Fix potential memory leak.")

        Apart from checking if stop() is doing its job properly, see screenshot-01.png for some other complications.

        Show
        yip.ng added a comment - Cleanup supposed to be done by Ice.modal.stop(). This function existed as early as 2006. (Check-in comment was "Fix potential memory leak.") Apart from checking if stop() is doing its job properly, see screenshot-01.png for some other complications.
        Hide
        yip.ng added a comment - - edited

        iframe still exists in onElementUpdate phase, therefore should use onElementUpdate instead of onElementRemove. But changing to use onElementUpdate doesn't seem to help a bit, even though debugging of stop() in IE8 shows it does execute the iframe cleanup code:

        Event.stopObserving(window, "resize", iframe.resize);
        Event.stopObserving(window, "scroll", iframe.resize);
        iframe.resize = null;
        iframe.parentNode.removeChild(iframe.nextSibling);
        iframe.parentNode.removeChild(iframe);

        Show
        yip.ng added a comment - - edited iframe still exists in onElementUpdate phase, therefore should use onElementUpdate instead of onElementRemove. But changing to use onElementUpdate doesn't seem to help a bit, even though debugging of stop() in IE8 shows it does execute the iframe cleanup code: Event.stopObserving(window, "resize", iframe.resize); Event.stopObserving(window, "scroll", iframe.resize); iframe.resize = null; iframe.parentNode.removeChild(iframe.nextSibling); iframe.parentNode.removeChild(iframe);
        Ken Fyten made changes -
        Fix Version/s EE-3.2.0.GA [ 10332 ]
        Ken Fyten made changes -
        Assignee yip.ng [ yip.ng ] Mircea Toma [ mircea.toma ]
        Ken Fyten made changes -
        Assignee Priority P2 [ 10011 ] P1 [ 10010 ]
        Repository Revision Date User Message
        ICEsoft Public SVN Repository #32848 Mon Dec 17 15:39:21 MST 2012 mircea.toma ICE-8555 Modified Ice.modal.stop() function to clear the callbacks registered on the iframe's document and window objects (used for mouse and keyboard event draining). Also modified PanelPopupRenderer to use ice.onelementUpdate registration function for the callback that invokes Ice.modal.stop(), this way callback is invoked on before update just before the bridge will remove all updated iframes.
        Files Changed
        Commit graph MODIFY /icefaces3/trunk/icefaces/compat/components/src/main/java/com/icesoft/faces/component/panelpopup/PanelPopupRenderer.java
        Commit graph MODIFY /icefaces3/trunk/icefaces/compat/core/src/main/javascript/extras/extras.js
        Hide
        Mircea Toma added a comment -

        Modified Ice.modal.stop() function to clear the callbacks registered on the iframe's document and window objects (used for mouse and keyboard event draining). This in effects solves the memory leak ( see http://support.microsoft.com/kb/2714930 ).
        Also, modified PanelPopupRenderer to use ice.onElementUpdate registration function instead of ice.onElementRemove for the callback that invokes Ice.modal.stop(), this way the callback is invoked before the update is applied having thus the chance to still access the iframe it needs to work on.

        Show
        Mircea Toma added a comment - Modified Ice.modal.stop() function to clear the callbacks registered on the iframe's document and window objects (used for mouse and keyboard event draining). This in effects solves the memory leak ( see http://support.microsoft.com/kb/2714930 ). Also, modified PanelPopupRenderer to use ice.onElementUpdate registration function instead of ice.onElementRemove for the callback that invokes Ice.modal.stop(), this way the callback is invoked before the update is applied having thus the chance to still access the iframe it needs to work on.
        Mircea Toma made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Ken Fyten made changes -
        Security Private [ 10001 ]
        Ken Fyten made changes -
        Summary CLONE -ice:panelPopup leaking memory when displayed and hidden ice:panelPopup leaking memory when displayed and hidden
        Ken Fyten made changes -
        Fix Version/s EE-3.2.0.BETA [ 10573 ]
        Hide
        Arran Mccullough added a comment -

        Found a regression with these changes. Customer has an ace:fileEntry used in a modal ice:panelPopup. When the popup is closed with an h:commandButton, the underlying input components tabindex remains at -1 making them non-functional. If the fileEntry is removed or the h:commandButton is changed to an ice:commandButton this behavior is not need. The h:commandButton is a different button than what is used for the upload. I'll attach a basic test case showing this issue.

        Show
        Arran Mccullough added a comment - Found a regression with these changes. Customer has an ace:fileEntry used in a modal ice:panelPopup. When the popup is closed with an h:commandButton, the underlying input components tabindex remains at -1 making them non-functional. If the fileEntry is removed or the h:commandButton is changed to an ice:commandButton this behavior is not need. The h:commandButton is a different button than what is used for the upload. I'll attach a basic test case showing this issue.
        Arran Mccullough made changes -
        Resolution Fixed [ 1 ]
        Status Resolved [ 5 ] Reopened [ 4 ]
        Hide
        Arran Mccullough added a comment -

        Attached test case that shows recent issue.

        Steps:

        • Load welcomeICEfaces.jsf
        • Click on the Open Button, modal panelPopup is shown that includes an ace:fileEntry, Upload button, and two Cancel buttons.
        • Clicking on the "ICE - Cancel" button closes the popup and the popup can be reoponed.
        • Clicking on the "H - Cancel" button closed the popup but it can't be reopened.
        • Looking at the source of the Open button, its tabindex is set to -1 even though the modal layer is gone.
        Show
        Arran Mccullough added a comment - Attached test case that shows recent issue. Steps: Load welcomeICEfaces.jsf Click on the Open Button, modal panelPopup is shown that includes an ace:fileEntry, Upload button, and two Cancel buttons. Clicking on the "ICE - Cancel" button closes the popup and the popup can be reoponed. Clicking on the "H - Cancel" button closed the popup but it can't be reopened. Looking at the source of the Open button, its tabindex is set to -1 even though the modal layer is gone.
        Arran Mccullough made changes -
        Attachment FileEntryPopupTest.zip [ 15300 ]
        Attachment FileEntryPopupTestWAR.zip [ 15301 ]
        Hide
        Mircea Toma added a comment -

        The recent issue is caused by the use of ace:fileEntry, this component disables the form submit capturing and it does its own form submit. When the form submit does not go through jsf.ajax.request function the ice.onElementUpdate callbacks are not invoked, causing the onclick, onkeypress, onleyup and onkeydown callbacks that block the interaction with elements underneath the modal overlay to not be cleared when the modal popup is closed. This is the reason why the "Open" button does not respond, the click events are blocked by the overlay iframe (which is still present but hidden).

        Show
        Mircea Toma added a comment - The recent issue is caused by the use of ace:fileEntry, this component disables the form submit capturing and it does its own form submit. When the form submit does not go through jsf.ajax.request function the ice.onElementUpdate callbacks are not invoked, causing the onclick, onkeypress, onleyup and onkeydown callbacks that block the interaction with elements underneath the modal overlay to not be cleared when the modal popup is closed. This is the reason why the "Open" button does not respond, the click events are blocked by the overlay iframe (which is still present but hidden).
        Hide
        Mircea Toma added a comment -

        Reverting the changes for PanelPopupRenderer to register the iframe cleanup code with ice.onElementRemove is not possible because ice.onElementRemove callbacks are invoked after the updates are applied, too late for the callback code to cleanup the memory leak inducing callbacks.

        Show
        Mircea Toma added a comment - Reverting the changes for PanelPopupRenderer to register the iframe cleanup code with ice.onElementRemove is not possible because ice.onElementRemove callbacks are invoked after the updates are applied, too late for the callback code to cleanup the memory leak inducing callbacks.
        Hide
        Mircea Toma added a comment -

        Changing the file entry renderer to do its own form submit only when the "Upload" button is clicked is not possible because the button is rendered by a plain h:commandButton component.

        Show
        Mircea Toma added a comment - Changing the file entry renderer to do its own form submit only when the "Upload" button is clicked is not possible because the button is rendered by a plain h:commandButton component.
        Hide
        Mircea Toma added a comment -

        The simplest and quite correct workaround is to add the f:ajax or ace:ajax tag to the "Cancel" h:commandButton. This way the ICEfaces form submit is executed and ice.onElementUpdate callbacks are invoked. Also when the "Cancel" button is clicked the file upload will not proceed, this is the correct part since you don't want to upload the file but to cancel instead.

        Show
        Mircea Toma added a comment - The simplest and quite correct workaround is to add the f:ajax or ace:ajax tag to the "Cancel" h:commandButton. This way the ICEfaces form submit is executed and ice.onElementUpdate callbacks are invoked. Also when the "Cancel" button is clicked the file upload will not proceed, this is the correct part since you don't want to upload the file but to cancel instead.
        Mircea Toma made changes -
        Workaround Description The simplest and quite correct workaround is to add the f:ajax or ace:ajax tag to the "Cancel" h:commandButton. This way the ICEfaces form submit is executed and ice.onElementUpdate callbacks are invoked. Also when the "Cancel" button is clicked the file upload will not proceed, this is the correct part since you don't want to upload the file but to cancel instead.
        Ken Fyten made changes -
        Status Reopened [ 4 ] Closed [ 6 ]
        Resolution Won't Fix [ 2 ]
        Ken Fyten made changes -
        Resolution Won't Fix [ 2 ]
        Status Closed [ 6 ] Reopened [ 4 ]
        Ken Fyten made changes -
        Status Reopened [ 4 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Ken Fyten made changes -
        Status Resolved [ 5 ] Closed [ 6 ]

          People

          • Assignee:
            Mircea Toma
            Reporter:
            Carlo Guglielmin
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: