Skip to content

Fix race condition in DoubleLocked#release #5153

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

Merged
merged 3 commits into from
May 19, 2025

Conversation

alexarchambault
Copy link
Collaborator

@alexarchambault alexarchambault commented May 19, 2025

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, which java.nio.channels.FileChannel doesn't allow (it throws an OverlappingFileLockException in that case).

This PR makes sure MillMain and MillDaemonMain use the same Lock.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 to Lock#{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, where

  • a first thread acquires the lock
  • a second one tries to acquire it, and waits for it
  • the first thread releases the lock

During 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

$ ./mill 'integration.feature[output-directory].packaged.daemon.testForked' "mill.integration.OutputDirectoryLockTests.basic"

for me, locally.

@lihaoyi
Copy link
Member

lihaoyi commented May 19, 2025

@alexarchambault can you fill out the PR description with your understanding of the problem and why this is the correct fix for it

@alexarchambault
Copy link
Collaborator Author

@lihaoyi Should be done

@alexarchambault alexarchambault marked this pull request as ready for review May 19, 2025 16:28
Copy link
Member

@lihaoyi lihaoyi left a comment

Choose a reason for hiding this comment

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

shipit

@alexarchambault alexarchambault merged commit 63bd1a6 into com-lihaoyi:main May 19, 2025
61 of 62 checks passed
@alexarchambault alexarchambault deleted the fix-race-condition branch May 19, 2025 18:12
@lefou lefou added this to the 1.0.0-RC1 milestone May 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants