-
Couldn't load subscription status.
- Fork 1.4k
Fix Queue#take dropping items on interruption
#10116
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
Conversation
|
|
||
| @deprecated("This method will be removed in a future release.", "2.1.21") | ||
| private[zio] def shouldInterrupt(): Boolean = | ||
| isInterruptible() && isInterrupted() |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might want to remove 🙂
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very clever
/fixes #9973
/fixes #9974
/claim #9973
This PR fixes two issues, which both contribute to
Queue#takedropping items:FiberRuntime)Queue#takedid 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:
FiberRuntimefile fix Interruption "gap" at the end ofuninterruptibleMask/restoreand/orasyncMaybe/asyncInterrupt#9974Queuefile fix Race condition when interruptingQueue#takecan cause items to disappear #9973Leaving 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