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

Skip to content

Conversation

@kyri-petrou
Copy link
Contributor

@kyri-petrou kyri-petrou commented Aug 16, 2025

/fixes #9973
/fixes #9974
/claim #9973

This PR fixes two issues, which both contribute to Queue#take dropping items:

  1. There is an interruption gap between uninterruptible regions (see changes under FiberRuntime)
  2. Queue#take did not take into account that it had to return items to the queue in case that the promise was already fulfilled (with interruption)

Note that:

Leaving as draft cause I want to go over the queue code once more with a fresh mind, and to see if CI agrees with my changes

Full disclaimer: While the solution seems rather simple, this was one of the hardest issues I ever worked on. Figuring out the changes needed to be done in FiberRuntime in a way that didn't break existing functionality took an enormous amount of time


@deprecated("This method will be removed in a future release.", "2.1.21")
private[zio] def shouldInterrupt(): Boolean =
isInterruptible() && isInterrupted()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can this just be def shouldInterrupt() = shouldInterrupt(true) for simplicity?

Copy link
Collaborator

Choose a reason for hiding this comment

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

You can ignore this, left before the recent set of changes.


private def removeTaker(taker: Promise[Nothing, A])(implicit trace: Trace): UIO[Unit] =
ZIO.succeed(takers.remove(taker))
private val interruptAsNone = ZIO.interruptAs(FiberId.None)(Trace.empty)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this belong in the object instead of the class itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, yes missed this 👍

import java.util.{Set => JavaSet}
import scala.annotation.tailrec

object Foo extends ZIOAppDefault {
Copy link
Collaborator

Choose a reason for hiding this comment

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

might want to remove 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Knew I forgot to delete some debugging code 😆

*/
private[this] def ignoreFlagsUpdate(update: RuntimeFlags.Patch, stackIndex: Int) = {
def isInterruptionDisabledInNextFrame(stackIndex: Int) =
_stack(stackIndex - 1) match {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we need a bounds check, but would abuse bite us later? Maybe an assertion we elide at runtime?

Copy link
Contributor Author

@kyri-petrou kyri-petrou Aug 19, 2025

Choose a reason for hiding this comment

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

There is already a lower bound check (size > 0) as the stack might be empty. But having an upper bound check isn't really useful as we'll get an exception anyways.

Having said that, I'll add an elided assertion that the stackIndex argument is the same as heap _stackSize variable just to make sure we're passing the right value (since we utilize a local variable instead of the heap one for performance)

// The promise was already completed, so if we interrupt here we'll drop the item
// This is not ideal but instead of interrupting we recover temporarily.
// Interruption will resume at the next point where it's enabled
p.await
Copy link
Collaborator

Choose a reason for hiding this comment

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

very clever

@kyri-petrou kyri-petrou marked this pull request as ready for review August 19, 2025 17:01
@kyri-petrou kyri-petrou enabled auto-merge (squash) September 29, 2025 15:13
@kyri-petrou kyri-petrou merged commit f0a12eb into zio:series/2.x Sep 29, 2025
19 checks passed
@kyri-petrou kyri-petrou deleted the fix-queue-take branch September 29, 2025 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

3 participants