-
-
Couldn't load subscription status.
- Fork 1.6k
Fix potential double acquisition in SingleLock
#3936
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Spock started to experience strange deadlocks the thread dumps point to the locking infrastructure being the culprit. I checked the JavaDoc of class ManagedLocker implements ManagedBlocker {
final ReentrantLock lock;
boolean hasLock = false;
ManagedLocker(ReentrantLock lock) { this.lock = lock; }
public boolean block() {
if (!hasLock)
lock.lock();
return true;
}
public boolean isReleasable() {
return hasLock || (hasLock = lock.tryLock());
}
}The JavaDoc suggests that this isn't the issue, although the example implementation guards against repeated locking, so I think we should follow its guidance.
|
|
I tried to test if this branch fixes the issue in Spock's CI jobs with the help of jitpack.io. Unfortunately, it fails to build. |
|
There was a time we used to provide a custom |
|
I went ahead and (temporarily) added such a configuration file to your branch in order to fix the build, right? Or does it have to be present in the
jdk:
- openjdk21
before_install:
- sdk install java 21.0.2-open
- sdk use java 21.0.2-open
install:
- ./gradlew --version
- ./gradlew publishToMavenLocal -x test |
|
https://jitpack.io/com/github/junit-team/junit5/leo~fix-potential-lock-isssue-SNAPSHOT/build.log now reports: Progress... now the Gradle Daemon "stalls" or so: |
|
The actual build was successful: I think this comes from jitpack as well as the actual error a bit further down From the help message it looks like they use an ancient gradle version to do something with the artifacts. Maybe it would help if we reset Java back to 8 after building. |
|
Back to did you do something to fix it? |
|
Mh, nothing special. Let me touch the file to trigger a recompilation... |
|
|
|
Yeah, I don't have sdk man, so I was just using whatever version Gemini suggested for Java 8. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing that! I wonder why this is only surfacing now... 🤷
`SingleLock` uses a `ForkJoinPool.ManagedBlocker` for efficient blocking in a fork-join pool. In the `isReleasable()` method it calls `tryLock()` without remembering the outcome. The `block` method also unconditionally called `lockInterruptibly()` even if the lock was already acquired. The problem that can arise is that the lock is acquired multiple times, but only released once. `CompositeLockManagedBlocker` is also updated, so that `block()` checks for `acquired` before locking.
7746959 to
98b4de9
Compare
This comment was marked as outdated.
This comment was marked as outdated.
Oops. This is a PR which cannot be reopened. See #3988 instead. |
SingleLockuses aForkJoinPool.ManagedBlockerfor efficient blocking in a fork-join pool. In theisReleasable()method it callstryLock()without remembering the outcome. Theblockmethod also unconditionally calledlockInterruptibly()even if the lock was already acquired. The problem that can arise is that the lock is acquired multiple times, but only released once.CompositeLockManagedBlockeris also updated, so thatblock()checks foracquiredbefore locking.Overview
I hereby agree to the terms of the JUnit Contributor License Agreement.
Definition of Done
@APIannotations