Fix webapp worker thread and classloader leak on undeploy#172
Open
fangornoftheforest wants to merge 1 commit into
Open
Fix webapp worker thread and classloader leak on undeploy#172fangornoftheforest wants to merge 1 commit into
fangornoftheforest wants to merge 1 commit into
Conversation
Three issues prevented clean shutdown of Argon2Function and BalloonHashingFunction executors in a servlet container lifecycle: 1. createExecutorService() registered a new Runtime shutdown hook on every call. Webapps that redeploy accumulated these hooks indefinitely; each hook pinned the undeployed webapp's classloader via its lambda, preventing garbage collection. 2. No public API existed to stop the workers. Runtime shutdown hooks only fire on JVM exit, not servlet contextDestroyed, so Tomcat's clearReferencesThreads consistently warned about password4j-worker threads on undeploy. 3. Even if a caller shut the executor down via reflection, the Argon2Function/BalloonHashingFunction INSTANCES caches still held references to instances whose executors had terminated, breaking subsequent hash calls. Changes: - Utils: single managed shutdown hook plus a static registry of executors. Registration is idempotent (guarded by a volatile hook reference). - Password.shutdown(): public static entry point to be called from ServletContextListener.contextDestroyed. Shuts down every tracked executor, clears the function-instance caches so future calls rebuild cleanly, and removes the JVM shutdown hook to free the classloader. - Argon2Function/BalloonHashingFunction: package-private clearInstances() used by the shutdown path. - PasswordTest: regression test covering thread termination and reuse after shutdown. Fixes Password4j#171 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Coauthored by Claude
Three issues prevented clean shutdown of Argon2Function and BalloonHashingFunction executors in a servlet container lifecycle:
createExecutorService() registered a new Runtime shutdown hook on every call. Webapps that redeploy accumulated these hooks indefinitely; each hook pinned the undeployed webapp's classloader via its lambda, preventing garbage collection.
No public API existed to stop the workers. Runtime shutdown hooks only fire on JVM exit, not servlet contextDestroyed, so Tomcat's clearReferencesThreads consistently warned about password4j-worker threads on undeploy.
Even if a caller shut the executor down via reflection, the Argon2Function/BalloonHashingFunction INSTANCES caches still held references to instances whose executors had terminated, breaking subsequent hash calls.
Changes:
Fixes #171: Failed to stop password4j-worker thread