allthingssecurity opened a new pull request, #28536: URL: https://github.com/apache/camel/pull/28536
# Description [CAMEL-26049](https://issues.apache.org/jira/browse/CAMEL-26049) Two resource leaks in camel-coap, both because Californium 3.14 only releases threads and sockets on `destroy()`: 1. `CoAPComponent.doStop` calls `stop()` on each `CoapServer` of its `servers` map, never `destroy()`, and keeps the map. `CoapServer.stop()` stops the endpoints but keeps the server's executors (`CoapServer(main)#N`, `CoapServer(secondary)#N`), whose threads are not daemon threads; only `destroy()` shuts them down. So after a CamelContext with a coap consumer is stopped, the JVM does not exit on its own (a standalone or Camel Main application, or a container that then needs a SIGKILL after the grace period), and every CamelContext started in the same JVM adds 3 more threads. 2. `CoAPProducer` creates its `CoapClient` on the first exchange with `CoAPEndpoint.createCoapClient`, which builds the client's own `CoapEndpoint` (a bound UDP socket with its receiver and sender threads, or the DTLS/TCP connector threads). `doStop` calls `client.shutdown()`, which in Californium 3.14 only shuts down the client's executors (read with javap) and does not destroy an endpoint set with `setEndpoint`. A route restart creates a new producer, so each restart (and each producer evicted from a `toD` or `ProducerTemplate` cache) leaks a bound socket and 2 or more threads. Changes: - `CoAPComponent.doStop` calls `destroy()` on the servers and clears the map. The consumers get their server from `getServer` on each start, so a CamelContext started again creates the servers again. `doStop` runs under the service lock that `getServer` also uses. - `CoAPProducer.doStop` destroys the endpoint of the client it created (after `client.shutdown()`). A client set on the component or the endpoint (`client` option) is not created by the producer and is left alone, as before. - A rare case changes: a producer that is stopped while another thread still has a request in flight on it, for example a producer that a `toD` or `ProducerTemplate` cache evicts while it is in use (a graceful route stop waits for the inflight exchanges first). Its endpoint is now destroyed, so that request gets no response: it waits until the client timeout or returns null earlier, and the exchange fails. On main only `client.shutdown()` ran, and the response still arrived. The error message then reads `client.getURI()` after `doStop` set `client` to null, which is a `NullPointerException`; that could already happen on main when no response came. - No option or generated file change. No upgrade guide entry: nothing for users to change. - Backport: camel-4.23.x, 4.22.x, 4.18.x and 4.14.x have the same code. Not changed (follow-up JIRAs if wanted): - The observe consumer (`CoAPObserver`, `observe=true`) also only calls `client.shutdown()` and keeps its client endpoint. There the endpoint must stay until the cancel request that `doStop` sends (`proactiveCancel()`, CAMEL-25742) has gone out, so destroying it right after the cancel is not the same small change. - `CoAPConsumer` has no `doStop`: a stopped route stays registered on its resource until another consumer takes the path. Tests: - New `CoAPComponentStopDestroysServersTest`, 2 tests, and `CoAPProducerStopDestroysEndpointTest`, 1 test, JUnit assertions as in the module. - `stoppingTheCamelContextReleasesTheServerThreads` (own `DefaultCamelContext` with a coap consumer, one GET, `stop()`) fails on main: `non-daemon CoapServer threads still alive after CamelContext.stop() ==> expected: <[]> but was: <[CoapServer(main)#1, CoapServer(secondary)#1, CoapServer(secondary)#2]>`. - `aCamelContextStartedAgainServesAgain` is a control that passes on main and with the fix: the server is created again after a context stop and start. - `routeRestartsReleaseTheEndpointsOfTheStoppedProducers` (5 restarts of a producer route, a request after each, then a stop) fails on main: `UDP receiver threads of stopped CoAP producers still alive after 5 restarts ==> expected: <0> but was: <10>`. - Unit tests of camel-coap with the fix: 85 run, 0 failures, 0 skipped (including the observe restart tests of CAMEL-25742). - The formatter and import-sort plugins ran. I built offline with `-Dasm-version=9.11` because asm 9.11.1 was not in my local repository. # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it): [CAMEL-26049](https://issues.apache.org/jira/browse/CAMEL-26049). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built camel-coap and ran its tests, including the formatter and import-sort plugins. No generated file changes. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- 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]
