Skip to content

Commit

Permalink
Merge pull request #3549 from durban/mutexCancel
Browse files Browse the repository at this point in the history
Fix mutex cancelled acquire
  • Loading branch information
djspiewak authored Apr 24, 2023
2 parents ab5d56c + c760a55 commit 4109aef
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 4 deletions.
8 changes: 4 additions & 4 deletions std/shared/src/main/scala/cats/effect/std/Mutex.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ object Mutex {
private[this] val waiters = new UnsafeUnbounded[Either[Throwable, Boolean] => Unit]
private[this] val FailureSignal = cats.effect.std.FailureSignal // prefetch

private[this] val acquire: F[Unit] = F
.asyncCheckAttempt[Boolean] { cb =>
private[this] val acquire: F[Unit] = F.uncancelable { poll =>
poll(F.asyncCheckAttempt[Boolean] { cb =>
F.delay {
if (locked.compareAndSet(false, true)) { // acquired
RightTrue
Expand All @@ -116,11 +116,11 @@ object Mutex {
}
}
}
}
.flatMap { acquired =>
}).flatMap { acquired =>
if (acquired) F.unit // home free
else acquire // wokened, but need to acquire
}
}

private[this] val _release: F[Unit] = F.delay {
try { // look for a waiter
Expand Down
17 changes: 17 additions & 0 deletions tests/shared/src/test/scala/cats/effect/std/MutexSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,22 @@ final class MutexSpec extends BaseSpec {
"not deadlock when highly contended" in real {
mutex.flatMap(_.lock.use_.parReplicateA_(10)).replicateA_(10000).as(true)
}

"handle cancelled acquire" in real {
val t = mutex.flatMap { m =>
val short = m.lock.use { _ => IO.sleep(5.millis) }
val long = m.lock.use { _ => IO.sleep(50.millis) }
val tsk = IO.race(short, long).flatMap { _ =>
// this will hang if a cancelled
// acquire left the mutex in an
// invalid state:
m.lock.use_
}

tsk.replicateA_(1000)
}

t mustEqual (())
}
}
}

0 comments on commit 4109aef

Please sign in to comment.