Infinite JavaScript loop in certain situations

Created on 4 May 2018, about 6 years ago
Updated 16 May 2023, about 1 year ago

We've discovered an infinite loop in the JavaScript code for AcquiaPurgeAjaxProcessor.js.

Here's the situation:

1. User edits a page on their site.
2. Subsequent page load begins the AJAX processor for the queue of paths that were just added to be purged.
3. User closes their laptop before the queue is finished, pausing the JavaScript execution in their browser.
4. Days later, user returns and re-opens their laptop.
5. Browser resumes JavaScript state and beings trying to finish purging the paths from a couple days ago.
6. However, the user's session in Drupal has ended. Normally this would result in a 403 error response for the /acquia_purge_ajax_processor path, but our site has the r4032login module enabled, which redirects 403 responses to the user/login page, which ultimately returns a 200 status code.
7. The jQuery AJAX "error" callback is executed, since the response is not JSON as it expects.
8. The error callback runs this logic:

// Sometimes requests randomly fail with HTTP 200 (OK), continue
// processing requests as it most probably just did its work.
if (Number(request['status']) == 200) {
  if (uiActivated()) {
    uiThrobberOff();
  }
  eventLoopRun();
}

// 403 responses indicate the backend logged out, quit.
else if (Number(request['status']) == 403) {
  if (uiActivated()) {
    uiTearDown();
  }
  quit();
}

Since the HTTP response is 200, the JS code just tries again, repeating the whole process.

The only way to stop it is for the user to close their browser.

This has happened to us twice in the past month or so on a large Drupal 7 multisite platform we maintain (so, lots of editors, increased chance of something like this occurring).

I think the core problem is that if jQuery AJAX invokes the error callback, and the response is a 200, Acquia Purge cannot assume that it should simply try again. The error callback is invoked in this case because the response that was returned is not JSON. I'm not sure what initially prompted that block of code that does a re-try on a 200 response (you may remember?), so not sure if it can be removed.

I think for now we will patch it with a counter that backs out after 100 attempts or something to short-circuit the infinite loop.

πŸ› Bug report
Status

Fixed

Version

1.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States bkosborne New Jersey, USA

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.69.0 2024