Joerg Hoh created SLING-13261:
---------------------------------
Summary: Racecondition when resolving servlets
Key: SLING-13261
URL: https://issues.apache.org/jira/browse/SLING-13261
Project: Sling
Issue Type: Task
Components: Servlets
Affects Versions: Servlets Resolver 3.0.6
Reporter: Joerg Hoh
h3. Summary
When two servlets are registered for the same resource type, method and
extension, the {{SlingServletResolver}} can intermittently resolve and execute
the _wrong_ servlet. The incorrect servlet is served from the
{{ResolutionCache}} and continues to be served for that request signature until
the cache is next flushed. The problem is timing-dependent, so in the vast
majority of cases the correct servlet is resolved under identical load.
h3. Root cause
Both servlets collapse onto a single {{ResolutionCache}} key (the key is
derived from resource type/super type, extension, method and selectors — not
from the servlet identity), and the winner is decided by service ranking. The
cache is populated in {{SlingServletResolver.getServletInternal()}} via a
non-atomic _get → resolve → put_ sequence with no guard against a concurrent
{{{}ResolutionCache.flushCache(){}}}.
When the (higher-ranked) servlet registers, the resource tree immediately
starts resolving to it and the cache is flushed. If a resolution that already
read the _old_ winner from the tree performs its {{put}} _after_ that flush, it
re-inserts the now-stale servlet into the just-flushed cache. That entry then
survives and is served to every subsequent request for the same key until an
unrelated flush clears it.
The window is small (a single resolution's collect-to-put span) and only armed
while the key is in a miss state around the registration, which is why the
failure is rare and intermittent. Any later flush (content change,
script-engine/adapter event, JMX {{{}flushCache{}}}, etc.) heals it
permanently, because once the correct servlet is the stable tree winner,
re-population can only ever cache the correct servlet.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)