Problem/Motivation
Note: discovered while working on #3580666: Autologout kills the dynamic page cache for all authenticated users
When a user extends their session via the dialog, the module works correctly the first time. On the second (or later) extend, the user is unexpectedly logged out or the dialog appears at inconsistent times.
Root cause
Multiple places in autologout.js set t = setTimeout(...) or paddingTimer = setTimeout(...) without first calling clearTimeout() on the existing timer. This causes multiple concurrent timer callbacks to accumulate over time, resulting in erratic behavior.
Steps to reproduce
- Set a short timeout (e.g. 10s) and padding (e.g. 5s)
ddev drush config:set autologout.settings timeout 10 -y
ddev drush config:set autologout.settings padding 5 -y- Log in
- Wait for the dialog to appear, click Yes
- Wait for the dialog to appear again, click Yes
- User is logged out despite clicking Yes
Proposed resolution
Introduce two small helper functions that encapsulate clearTimeout + setTimeout, making it structurally impossible to accidentally leave an orphaned timer.
Remaining tasks
do it
User interface changes
N/A
API changes
N/A
Data model changes
N/A
Issue fork autologout-3580664
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
herved commentedComment #4
ericgsmith commentedConfirmed the bug as reported - code changes look good and resolves the issue.
Comment #6
the_g_bomb commentedUpdated the fork; it would be good to get a test in place to protect this.
May need a rebase
Comment #7
ericgsmith commentedSetting to needs work based on above need for test
Comment #8
ericgsmith commentedAdded a test that passes - test only job fails - https://git.drupalcode.org/issue/autologout-3580664/-/jobs/9091331
This is not great test really as I found I needed to add up to a 30 second allowance to the wait for element as the activity reset timer is hard coded to 30 seconds - I wonder if we should add some logic to change this if the timeout is less than 30 seconds, use the timeout value? Haven't looked too close to what that activity reset is doing.
Comment #9
herved commentedSorry for the late reply.
I initially wrote a test - actually updating the existing one in AutologoutCookieTest - and noticed the same 30s delay.
I don't think waiting for that long in tests is a viable option. This arbitrary 30s delay also doesn't make sense to me. I think the whole
activityResetTimershould be deleted and then in init we could just:So it will just follow the main timeout.
Also, why is it altering the settings var, from drupalSettings, and not using a local var?
Comment #10
ericgsmith commented@herved that sounds sensible - do you think that should be done here or in a follow up / separate issue?
My concern is that there is a lot of open issues touching the JS and it would be good to get this fixed before widening the scope - #3395581: Autologout can log out from other tabs/windows appears to remove the 30 seconds as well so not sure how much would be covered if that issue lands.
What if we just mark this test as skipped - @the_g_bomb - we have demonstrated the issue via the test but the downside (an additional 1 minute to run a single test) is not really worth it - can we mark it skipped for now pending a follow up to remove the 30s timer?
Comment #11
ericgsmith commentedI've marked the test as skipped - not ideal introducing a test that isn't running, but I think getting this fix in is pretty important to be able to accurately test and fix other issues - and given other issues like #3395581 are (indirectly) tackling the activity reset timer, I don't think we should widen the scope of this issue to fix that here.
@the_g_bomb is there anything else needed here to get this in? I think my RTBC of the @herved’s changes is still valid although leaving needs review for the test / test conversation.
Comment #12
the_g_bomb commentedSorry, I've been really busy at work, and I hope to get back to this asap. Happy to leave the tests until a follow-up ticket.
Comment #13
benstallings commented1. JS timer accumulation fix (4e99d0b) — Good fix. The core issue is that setTimeout was called repeatedly without clearing previous timers, causing multiple concurrent
timeouts that could trigger premature logout. The schedule() / schedulePadding() wrapper pattern is clean and correct:
- Each call to schedule() clears timeoutTimer before setting a new one
- Each call to schedulePadding() clears paddingTimer before setting a new one
- All 7 setTimeout call sites are covered
One minor note: Math.max(0, localSettings.timeout - difference) on line 283 is a good defensive addition — prevents negative delays if the clock difference exceeds timeout.
2. Test (baba1c9 + 53395e4) — The test is immediately markTestSkipped due to the 30-second hardcoded activity reset timer making it impractically slow. This means:
- The test documents intent but provides no CI coverage
- It won't catch regressions
Comment #14
the_g_bomb commentedFinally got around to testing this myself and merging.
Thank you all.