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]
