francescomari opened a new pull request, #481:
URL: https://github.com/apache/felix-dev/pull/481

   ## Summary
   
   A `NullPointerException` in `WhiteboardManager.deactivate()` during a 
configuration-triggered Jetty restart causes the shutdown sequence to abort. 
Because neither `stopJetty()` nor `updated()` catch the exception, 
`startJetty()` is never called — the server keeps running with a corrupted 
`WhiteboardManager`, all subsequent servlet registrations fail with 
`IndexOutOfBoundsException`, and the system is permanently unusable until the 
JVM is restarted.
   
   ## Root cause
   
   Three bugs compound into one unrecoverable failure:
   
   1. **`WhiteboardManager.deactivate()`** calls 
`handler.getRegistry().getEventListenerRegistry()` without a null check. 
Context handlers that were never fully activated have a null registry, causing 
an NPE.
   
   2. **`WhiteboardManager.stop()`** has no exception handling around its 
tracker-close loop. The NPE from (1) propagates out before `contextMap.clear()` 
is reached, leaving stale, partially-deactivated entries and remaining trackers 
still open.
   
   3. **`JettyService.stopJetty()`** has no exception handling around 
`controller.unregister()`. The NPE propagates through `stopJetty()` and out of 
`updated()`, so `server.stop()` is never called (the old server keeps running) 
and `startJetty()` is never reached (no new `WhiteboardManager` is created).
   
   Additionally, `getMatchingContexts()` and `getContextHandler()` call 
`handlerList.get(0)` without checking for empty lists. Empty lists can appear 
in `contextMap` via the retry loop in `removeContextHelper()`, which can drain 
a list without removing it from the map.
   
   ## Changes
   
   - **`WhiteboardManager.deactivate()`**: guard `handler.getRegistry()` 
against null before calling `getEventListenerRegistry().contextDestroyed()`
   - **`WhiteboardManager.stop()`**: wrap each `tracker.close()` in a try-catch 
so the loop always completes and `contextMap.clear()` is always reached
   - **`WhiteboardManager.getMatchingContexts()` / `getContextHandler()`**: 
skip empty handler lists instead of calling `.get(0)` on them
   - **`WhiteboardManager.removeContextHelper()`**: remove the map entry when 
the retry loop drains a handler list to empty
   - **`JettyService.stopJetty()`** (both jetty and jetty12): wrap 
`controller.unregister()` in a try-catch so `server.stop()` and the rest of 
shutdown always execute, and `startJetty()` is always reached in `updated()`


-- 
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