joerghoh opened a new pull request, #68:
URL: https://github.com/apache/sling-org-apache-sling-servlets-resolver/pull/68

   When two servlets are registered for the same resource type, method and 
extension, SlingServletResolver can intermittently resolve and execute the 
wrong servlet, served from the ResolutionCache.
   
   Both servlets collapse onto a single cache key (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 
resolves to it and the cache is flushed. If a resolution that already read the 
old winner performs its put after that flush, it re-inserts the now-stale 
servlet into the just-flushed cache. That entry survives and is served for 
every following request with the same key until an unrelated flush clears it.
   
   The race window is tiny (a single resolution's collect-to-put span) and only 
armed while the key is in a miss state around the registration, so it works in 
the vast majority of cases under identical load — matching the observed 
intermittent behaviour.
   
   **Solution**
   
   - Add a monotonic generation counter to ResolutionCache, incremented on 
every flushCache().
   - getServletInternal() captures the generation before resolving and passes 
it to put(); the candidate is cached only if the generation is unchanged (i.e. 
no flush occurred during the resolution).
   - A ReadWriteLock keeps the generation check and the insert atomic with 
respect to a flush: put() takes the read lock (puts stay concurrent), 
flushCache() takes the write lock. Flushes are rare, so there is no meaningful 
contention on the hot path.
   - No behavioural change beyond rejecting cache writes that a flush has 
invalidated; a rejected write simply causes the next request to re-resolve and 
re-cache.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to