Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Race condition when interrupting Queue#take can cause items to disappear #9973

@kyri-petrou

Description

@kyri-petrou

A possibly more reliable repro:

final object ReproZio extends zio.ZIOAppDefault {

  import java.util.concurrent.atomic.AtomicReference
  import zio._

  override def run = ZIO.unit.flatMap { _ =>
    val t = for {
      q <- Queue.unbounded[String]
      ref <- ZIO.attempt { new AtomicReference[String] }
      fib <- ZIO.uninterruptibleMask { restore =>
        restore(q.take).flatMap { item =>
          ZIO.attempt { ref.set(item) }
        }
      }.forkDaemon
      _ <- ZIO.sleep(Duration.fromMillis(10L))
      _ <- fib.interrupt zipPar q.offer("foo")
      _ <- fib.await
      s <- ZIO.attempt(ref.get())
      _ <- if (s eq null) {
        // take was cancelled, item should be in q
        q.take.flatMap { item =>
          if (item != "foo") ZIO.die(new AssertionError("incorrect item: " + item))
          else ZIO.unit
        }
      } else {
        // take was completed, q should be empty
        q.isEmpty.flatMap { empty =>
          if (!empty) ZIO.die(new AssertionError("nonempty q after completed take"))
          else ZIO.unit
        }
      }
      _ <- ZIO.attempt(println("ok"))
    } yield ()
    t.repeatN(99)
  }
}

This hangs for me with 2.1.19. So yes, it still seems to happen.

Originally posted by @durban in #4269

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions