Skip to content

fix(session): prevent modx_session table overflow (installer check + fallback GC)#16927

Closed
Ibochkarev wants to merge 2 commits intomodxcms:3.xfrom
Ibochkarev:fix/session-table-overflow-16275
Closed

fix(session): prevent modx_session table overflow (installer check + fallback GC)#16927
Ibochkarev wants to merge 2 commits intomodxcms:3.xfrom
Ibochkarev:fix/session-table-overflow-16275

Conversation

@Ibochkarev
Copy link
Copy Markdown
Collaborator

@Ibochkarev Ibochkarev commented Mar 14, 2026

What does it do?

  • Installer: Session GC check is now a blocking test. Adds isSessionGcEnabled(); uses pass when PHP session GC is enabled (or ini_set('session.gc_probability', 1) succeeds), fail otherwise. Fail message includes instructions for Ubuntu/Debian, links to PHP session configuration and Ubuntu bug #316441, and notes that MODX will still clean sessions via built-in fallback when that option is enabled.
  • modSessionHandler: Adds tryFallbackGc() — runs session GC periodically (throttled by session_gc_fallback_interval via cache) when PHP never calls gc() (e.g. session.gc_probability = 0 on Ubuntu/Debian). Called from open(). On failure, errors are logged and not rethrown so the session still opens.
  • modSessionHandler::gc($max): Uses the $max parameter for interface compliance (fallback to gcMaxLifetime when $max <= 0). Returns (int) count or false; PHPDoc @return int|false. No union return type in signature (PHP 7.4 compatible).
  • New system settings: session_gc_fallback_enabled (boolean, default true), session_gc_fallback_interval (seconds, default 3600). Transport and English lexicon added. Lexicon notes that throttling uses cache and fallback does not run when cache is unavailable.

Why is it needed?

The modx_session table can grow without bound (e.g. to gigabytes) when PHP never invokes the session handler’s gc() — commonly on Ubuntu/Debian where session.gc_probability = 0 by default (see issue #775). Not all hostings allow changing php.ini. This change (1) makes the installer fail clearly when GC is disabled and not fixable via ini_set, with guidance and links, and (2) adds a built-in fallback that runs GC at a configurable interval so the session table is still cleaned even when PHP never calls gc().

How to test

  1. Installer: Run setup on an environment with session.gc_probability = 0 (and ini_set disabled if possible). Confirm the session GC step fails with the new message (Ubuntu/Debian, php.ini, links). Set session.gc_probability = 1 in php.ini (or allow ini_set) and confirm the step passes.
  2. Fallback GC: Use database sessions (session_handler_class = modSessionHandler). Set session_gc_fallback_interval to a small value (e.g. 60). Ensure cache is available. Create expired session rows (e.g. set access to old timestamp). Trigger requests that open a session; after the interval, expired rows should be removed. Confirm in logs that no errors occur when GC runs; if DB is unavailable during fallback GC, confirm error is logged and session still opens.
  3. gc($max): When PHP calls gc($max), confirm that the lifetime used for deletion respects the passed $max (e.g. by inspecting behavior when session.gc_maxlifetime differs from MODX session_gc_maxlifetime).

Related issue(s)/PR(s)

  • Resolves #16275 — Solve the modx_session table overflow problem.
  • Refs #775 — Sessions garbage collector not used? (Ubuntu/Debian session.gc_probability = 0, workaround script, docs).

…fallback GC)

- Installer: block install when session.gc_probability=0 and ini_set fails; pass/fail instead of warn
- Installer: isSessionGcEnabled() helper; fail message with Ubuntu/Debian and PHP/issue links
- modSessionHandler: tryFallbackGc() with interval-based throttling via cache
- modSessionHandler: gc($max) uses $max for interface compliance, fallback to gcMaxLifetime
- modSessionHandler: try-catch in tryFallbackGc so session still opens on GC failure
- New settings: session_gc_fallback_enabled, session_gc_fallback_interval (transport + lexicon)

Refs modxcms#16275, modxcms#775
@opengeek
Copy link
Copy Markdown
Member

This is invalid. PHP calls gc based on PHP ini settings.

@opengeek opengeek closed this Mar 14, 2026
@Ibochkarev
Copy link
Copy Markdown
Collaborator Author

@opengeek Hi! Can we leave comments in the ones indicated in the description of the Pr issue and close them?

@Ibochkarev Ibochkarev deleted the fix/session-table-overflow-16275 branch March 15, 2026 13:52
@opengeek
Copy link
Copy Markdown
Member

@opengeek Hi! Can we leave comments in the ones indicated in the description of the Pr issue and close them?

That is what I have been suggesting. Researching and/or commenting in issues to explore if there is a good solution to pursue an implementation of in this space before submitting PRs would be much more helpful. Increasing the cognitive workload by brute forcing a solution on an issue that was previously identified as not a bug in many places is not helpful. What WOULD be helpful is researching/commenting on/managing issues you are using to create these PRs. In this way we can bring attention to them and encourage collaborative discussions from all stakeholders. Identifying the merit of the issue is much easier without integrators being asked to explore an implementation which attempts to address said issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Solve the modx_session table overflow problem

2 participants