Skip to content

Conversation

@owen-mc
Copy link
Contributor

@owen-mc owen-mc commented Jan 27, 2026

Previously it was not clear that this query applies to any class with lock and unlock methods.

I looked into whether to limit this to just classes which implement java.util.concurrent.locks.Lock (which account for ~2/3 of alerts) but found that custom lock types were all TPs except the one io.questdb.cairo.pool.WriterPool. I have now excluded types with names ending in "Pool" as they manage a collection of resources and the lock and unlock methods may be called for different resources. And I've added a test for this.

Copilot AI review requested due to automatic review settings January 27, 2026 15:50
@owen-mc owen-mc requested a review from a team as a code owner January 27, 2026 15:50
@github-actions
Copy link
Contributor

QHelp previews:

java/ql/src/Likely Bugs/Concurrency/UnreleasedLock.qhelp

Unreleased lock

When a thread acquires a lock it must make sure to unlock it again; failing to do so can lead to deadlocks. If a lock allows a thread to acquire it multiple times, for example java.util.concurrent.locks.ReentrantLock, then the number of locks must match the number of unlocks in order to fully release the lock.

Any class that has both lock and unlock methods is considered a lock type. However, classes with names ending in "Pool" are excluded, as they typically manage a collection of resources.

Recommendation

It is recommended practice always to immediately follow a call to lock with a try block and place the call to unlock inside the finally block. Beware of calls inside the finally block that could cause exceptions, as this may result in skipping the call to unlock.

Example

The typical pattern for using locks safely looks like this:

public void m() {
   lock.lock();
   // A
   try {
      // ... method body
   } finally {
      // B
      lock.unlock();
   }
}

If any code that can cause a premature method exit (for example by throwing an exception) is inserted at either point A or B then the method might not unlock, so this should be avoided.

References

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request improves the java/unreleased-lock query by excluding lock types with names ending in "Pool" to reduce false positives. Pool classes typically manage collections of resources where lock/unlock methods operate on individual resources rather than the pool itself.

Changes:

  • Added exclusion pattern to LockType class to filter out types with names ending in "Pool"
  • Updated documentation in comments and qhelp to clarify which classes are considered lock types
  • Added test case to verify that Pool-suffixed classes are properly excluded from the query

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
java/ql/lib/semmle/code/java/Concurrency.qll Added not this.getName().matches("%Pool") exclusion to LockType class and updated documentation comments
java/ql/test/query-tests/UnreleasedLock/UnreleasedLock.java Added TestPool class and good11 test method to verify Pool classes are excluded
java/ql/lib/change-notes/2026-01-27-unreleased-lock-pools.md Documented the change as a minor analysis improvement that reduces false positives

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@aschackmull aschackmull left a comment

Choose a reason for hiding this comment

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

Sounds reasonable. 👍

@owen-mc owen-mc merged commit a35e7b2 into github:main Jan 28, 2026
28 of 29 checks passed
@owen-mc owen-mc deleted the java/update-qhelp-unrelease-lock branch January 28, 2026 09:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants