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)

Reply via email to