Fix race condition in DoubleLocked#release #5153
Merged
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.
This PR makes some uses of
DoubleLock
safer, and fixes a race condition with it.DoubleLock
is basically used as a wrapper around a file lock (second lock), using it alongside a memory lock (first lock), that acts as a mutex for it. That way, the same JVM process doesn't try to acquire the file lock twice at the same time in a given JVM, whichjava.nio.channels.FileChannel
doesn't allow (it throws anOverlappingFileLockException
in that case).This PR makes sure
MillMain
andMillDaemonMain
use the sameLock.memory()
instance as a guard when trying to acquire a lock for the output directory. This doesn't solve the issue I was running into (see below), but seems to be safer nonetheless.It also tries to dispose of locks in
DoubleLock
in case calls toLock#{lock,tryLock}
throw.Lastly, it releases the two locks in
DoubleLocked
in the reverse order that they were acquired. This fixes the test case below. Doing so fixes a race condition, whereDuring the third step, releasing the memory lock before the file lock makes the second thread acquire the memory lock, and then possibly try to acquire the file lock, before the first thread is done releasing the file lock. The JVM doesn't allow this, and the second thread gets an
OverlappingFileLockException
.See the discussion in #5152 too
This fixes
for me, locally.