From 4f09b547652b2feaf836b92f71a28cf8197e98c2 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 6 Dec 2023 10:35:44 -0500 Subject: [PATCH] channels: fix memory ordering violation in iterate (#52407) Channel `iterate` calls might miss trailing items without this patch. I have not seen proof of this reaching a failure, but we do appear to be missing this ordering specification in visual review. Should not make a difference to generated code on x86, which already has TSO guaranteed, but may alter optimizations and other CPUs with weaker memory orderings. (cherry picked from commit 856e1120a8f255e4907a05f0146a2026a6665dd4) --- base/channels.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/base/channels.jl b/base/channels.jl index 90dac37f41cb6..75207e9fac76b 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -211,7 +211,12 @@ function close(c::Channel, @nospecialize(excp::Exception)) end nothing end -isopen(c::Channel) = ((@atomic :monotonic c.state) === :open) + +# Use acquire here to pair with release store in `close`, so that subsequent `isready` calls +# are forced to see `isready == true` if they see `isopen == false`. This means users must +# call `isopen` before `isready` if you are using the race-y APIs (or call `iterate`, which +# does this right for you). +isopen(c::Channel) = ((@atomic :acquire c.state) === :open) """ bind(chnl::Channel, task::Task)