Visitar URL original
Prune FileLockNamedLock thread entries and align the composite unlock error by slachiewicz · Pull Request #2300 · apache/maven-resolver · GitHub
Skip to content

Prune FileLockNamedLock thread entries and align the composite unlock error - #2300

Open
slachiewicz wants to merge 1 commit into
apache:masterfrom
slachiewicz:filelock-thread-steps-prune
Open

slachiewicz wants to merge 1 commit into
apache:masterfrom
slachiewicz:filelock-thread-steps-prune

Conversation

@slachiewicz

Copy link
Copy Markdown
Member

FileLockNamedLock.threadSteps kept an entry for every thread that ever used the lock, including threads whose attempt timed out, so it retained Thread objects for the lock's lifetime. Entries are now removed when a thread's step stack empties or its attempt fails.

CompositeNamedLock.doUnlock() threw NoSuchElementException for an unlock without a lock; it now throws the same IllegalStateException("Wrong API usage: unlock without lock") as the other locks, covered by unlockWoLockComposite for the three named-locks factories.

… error

threadSteps kept every thread that ever used the lock; CompositeNamedLock threw
NoSuchElementException instead of the IllegalStateException the other locks throw.
@slachiewicz slachiewicz added the bug Something isn't working label Nov 8, 2026
@slachiewicz
slachiewicz marked this pull request as ready for review November 8, 2026 22:40

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both fixes are correct. The thread-entry leak in FileLockNamedLock is a real memory/GC-root bug (threads held as map keys prevent GC after termination) fixed properly under criticalRegion. CompositeNamedLock.doUnlock() now aligns its exception semantics with the rest of the codebase. The new test correctly validates the composite fix — before this PR, steps.pop() on an empty ArrayDeque would throw NoSuchElementException, not IllegalStateException, causing assertThrows(IllegalStateException.class, ...) to fail.

Root cause: computeIfAbsent(Thread.currentThread(), ...) in doLockSharedPerform/doLockExclusivelyPerform creates map entries that are never cleaned up when lock acquisition times out. forgetThreadWithoutSteps() correctly addresses the timeout path; the doUnlock() restructuring (remove before anyOtherThreadHasSteps()) addresses the unlock path with a minor efficiency improvement.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants