This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch feature/WW-3576-session-map-staleness in repository https://gitbox.apache.org/repos/asf/struts.git
commit 8bd88a7c0a1f063dba351d793ff4a08b36ef982e Author: Lukasz Lenart <[email protected]> AuthorDate: Sun Oct 18 12:38:02 2026 +0200 WW-3576 docs: reflow the async detach clause Co-Authored-By: Claude Opus 5.5 <[email protected]> --- .../specs/2026-10-18-WW-3576-session-map-staleness-design.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/superpowers/specs/2026-10-18-WW-3576-session-map-staleness-design.md b/docs/superpowers/specs/2026-10-18-WW-3576-session-map-staleness-design.md index 0e79e03cd..07c8654cf 100644 --- a/docs/superpowers/specs/2026-10-18-WW-3576-session-map-staleness-design.md +++ b/docs/superpowers/specs/2026-10-18-WW-3576-session-map-staleness-design.md @@ -65,10 +65,11 @@ when that session dies (request threads), and one map that is stale *by design* - **Detached at request end (decided after the final review):** the request cleanup in the dispatcher detaches every `SessionMap` built for that request (each registers itself on the request at construction), not only the bound context's: this covers the original map left behind when - `createSession` replaces `ActionContext.SESSION`, and the maps of a nested forward. Detach (of all request maps, including the bound context's) is deferred while the request is in async mode, until the - async dispatch's cleanup. A detached map never calls its request again: with a live - pinned session it keeps working (async `Callable`s, stored `SessionAware` fields); a `put` with no live - pinned session throws `IllegalStateException`. Reason: a background thread (sandbox escape, custom + `createSession` replaces `ActionContext.SESSION`, and the maps of a nested forward. While the request + is in async mode, detach (of all request maps, including the bound context's) is deferred to the + async dispatch's cleanup. A detached map never calls its request again: with a live pinned session it + keeps working (async `Callable`s, stored `SessionAware` fields); a `put` with no live pinned session + throws `IllegalStateException`. Reason: a background thread (sandbox escape, custom `BackgroundProcess`) reaching `request.getSession(true)` after the request was recycled would write into another user's session. This also closes the same path for a never-pinned map used after its request ended, which predates this change. Detach is package-private.
