sheffatwork
sheffatwork

Reputation: 31

jQuery Ajax timeout leaves http request open, causing memory leaks on long-polling application

tl;dr: jQuery's ajax function does not appear to close http requests that time out. As such, each socket that is opened per each long-polling request never closes and the server eventually denies connections because of the number of open sockets. Is it possible to close these connections once they've timed out, so that I can kick off the next long-poll without worrying about endlessly opening [and subsequently orphaning] connections? If not, where am I going wrong with my approach to long-polling?

Note: I realize this is probably expected behavior, but I'm having a nightmare of a time following all of the moving parts and isolating my misunderstanding of the issue. Any guidance/clarity that you can offer will be greatly appreciated.

I've developed a simple application to demonstrate push-based notifications using lighttpd, cppcms (a C++ web framework), and jQuery. The client does this:

function listen(){
  $.ajax({
    url: "/push_test",
    type: "POST",
    timeout: 3000, // 3 seconds
    data: {
      will_leak: true
    },
    success: function(r){
      console.log("server responded: " r);
    },
    error: function(xhr, st, e){
      console.log("push_test error");
      console.dir(xhr);
      console.log("status: " + st);
      console.log("error: " + e);
    },
    complete: function(){
      //listen();
    }
  });
}

And then the server does something like this (I've done a similar test in the python Flask microframework with identical results to the following cppcms implementation):

void push_test()
{
    if(request().post("will_leak")){
        std::this_thread::sleep_for(std::chrono::seconds(5)); // Note client timeout of 3 seconds.
    }
    response().set_plain_text_header();
    response().out() << "If you see this on the client, we're all gucci";
    // Hint: if will_leak was true, you never see the above message.
}

Inspecting the network tab of Firefox's developer tools when the ajax call times out indicates that the HTTP request never returned a response or status code, but the console indicates the timeout failure in the "error" callback of the ajax call. A similar inspection of Chrome's developer tools's network tab indicates that the request was "cancelled" when we hit the timeout. Inspecting the open socket file descriptors on the server indicates that the sockets that have timed out are in the CLOSE_WAIT state and they remain that way until I've brought the server down and back up again.

Thanks if you've taken the time to read all of this, and let me know if you need any more information to help me isolate the issue here. I'm going to keep digging in the meantime.

Upvotes: 2

Views: 485

Answers (0)

Related Questions