Bug Tracker

Opened 10 years ago

Closed 9 years ago

Last modified 8 years ago

#6583 closed bug (invalid)

Memory retention caused by the use of timeout in ajax call

Reported by: huntc Owned by:
Priority: blocker Milestone: 1.5
Component: ajax Version: 1.5
Keywords: memory leak ajax timeout Cc:
Blocked by: Blocking:

Description (last modified by snover)

I find that when using the timeout option in an ajax call, and an error state is reached, and then followed by another call via a timer, memory is being retained. I have observed this on Mac OS X using Safari and Firefox. Here is a snippet of code that will reproduce the problem (I have also attached a complete project):

function get() {
  $.ajax({
    url: "file:///thisshouldfail",
    timeout: 1000,
    error: function(XMLHttpRequest, textStatus, errorThrown) {
      setTimeout(get, 100);
    }
  });
}

$(document).ready(function() {
  get();
});

To see the memory being retained please investigate the browser's resident memory size e.g. use the Unix 'top' command.

Attachments (2)

jQuery memory retention.zip (28.4 KB) - added by huntc 10 years ago.
Reproducible test case
jQuery memory retention 6583 fix.zip (49.7 KB) - added by huntc 10 years ago.
A patch of the 1.4.2 source that attends to the issue.

Download all attachments as: .zip

Change History (12)

Changed 10 years ago by huntc

Attachment: jQuery memory retention.zip added

Reproducible test case

comment:1 Changed 10 years ago by huntc

I've managed to identify the issue. If you receive an error and there is then a timeout i.e. the jQuery ajax timer fires (which it will if a timeout is specified), jQuery thinks that the request has not been completed. The error handler is then invoked again.

My recommendation is to set requestDone to true as the last statement of the complete() function. In addition I recommend the removal of setting requestDone to true at lines 5172 and 5179 (v.1.4.2 source file); this then keeps the setting of requestDone to just one place.

I have tested the fix and all is well with regards to memory being released.

I attach my modified source.

Changed 10 years ago by huntc

A patch of the 1.4.2 source that attends to the issue.

comment:2 Changed 10 years ago by huntc

I'm also wondering if any timer has been established then the timer should be cancelled by the completion routine. It would be possible for timers to bank up and retain the ajax object for requests that have been previously dealt with. Also, cancelling the timer seems in the completion routine sounds like a nice thing to do.

comment:3 Changed 10 years ago by huntc

I achieve the clearing of the timeout as follows:

Initialisation

 var requestDone = false;

 var timeoutId = null;

Handling timeout

  // Timeout checker
  if ( s.async && s.timeout > 0 ) {
    timeoutId = setTimeout(function() {
      // Check to see if the request is still happening
      if ( xhr && !requestDone ) {
        onreadystatechange( "timeout" );
      }
    }, s.timeout);
  }

Completion

  // Cancel any timer that has been established.
  if (timeoutId != null) {
    clearTimeout(timeoutId);
    timeoutId = null;
  }

  // Completion is recognised by setting requestDone.
  requestDone = true;

comment:4 Changed 9 years ago by snover

Milestone: 1.4.3

Resetting milestone to future.

comment:5 Changed 9 years ago by snover

Description: modified (diff)
Keywords: leak added; retention removed
Priority: undecided
Status: newopen

comment:6 Changed 9 years ago by snover

Milestone: 1.4.5
Priority: undecidedblocker
Version: 1.4.21.4.4

comment:7 Changed 9 years ago by snover

Resolution: invalid
Status: openclosed

So after investigating this I’m 100% convinced that there is no jQuery bug here—or at least, not in any version of Safari that I have available.

Unfortunately, what I have confirmed is that Safari appears to leak memory all on its own for any XMLHttpRequest (and this leak persists even after a window/tab is closed), no jQuery required, and there’s no way to prevent this from happening because it appears that it happens in the browser chrome (presumably because of the Activity panel).

So, yay for no bug in jQuery, but boo for Safari being a pile of crap with some apparently significant memory leaks related to network requests.

Last edited 9 years ago by snover (previous) (diff)

comment:8 Changed 9 years ago by huntc

Replying to snover:

So after investigating this I’m 100% convinced that there is no jQuery bug here—or at least, not in any version of Safari that I have available.

Thanks for the follow-up. How about the clearing of the timeout that I identified? Was that at least of interest in terms of being fixed?

Unfortunately, what I have confirmed is that Safari appears to leak memory all on its own for any XMLHttpRequest (and this leak persists even after a window/tab is closed), no jQuery required, and there’s no way to prevent this from happening because it appears that it happens in the browser chrome (presumably because of the Activity panel).

Has this been reported as an issue with WebKit? Can you please substantiate this one further?

comment:9 Changed 9 years ago by john

Version: 1.4.41.5

There wasn't a 1.4.5 release, was actually 1.5.

comment:10 Changed 9 years ago by john

Milestone: 1.4.51.5

There was no 1.4.5 release, was actually 1.5.

Note: See TracTickets for help on using tickets.