From e7d4ada817309c64d0f4213fd2fe4d170645f665 Mon Sep 17 00:00:00 2001 From: Jakob Nybo Nissen Date: Fri, 19 Jan 2024 19:26:10 +0100 Subject: [PATCH] Check task state on iterate Before, iterate on Channel would return `nothing` when the channel was closed, not checking if it was closed with an error. --- base/channels.jl | 9 +++++++++ test/channels.jl | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/base/channels.jl b/base/channels.jl index 3acbf37246a58..005fdd2aa29be 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -676,6 +676,15 @@ function iterate(c::Channel, state=nothing) end end else + # If the channel was closed with an exception, it needs to be thrown + if (@atomic :acquire c.state) === :closed + e = c.excp + if isa(e, InvalidStateException) && e.state === :closed + nothing + else + throw(e) + end + end return nothing end end diff --git a/test/channels.jl b/test/channels.jl index eed7a7ecc0566..4db792930bac0 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -499,12 +499,35 @@ end end end +struct CustomError <: Exception end + @testset "check_channel_state" begin c = Channel(1) close(c) @test !isopen(c) c.excp === nothing # to trigger the branch @test_throws InvalidStateException Base.check_channel_state(c) + + # Issue 52974 - closed channels with exceptions + # must be thrown on iteration, if channel is empty + c = Channel(2) + put!(c, 5) + close(c, CustomError()) + @test take!(c) == 5 + @test_throws CustomError iterate(c) + + c = Channel(Inf) + put!(c, 1) + close(c) + @test take!(c) == 1 + @test_throws InvalidStateException take!(c) + @test_throws InvalidStateException put!(c, 5) + + c = Channel(3) + put!(c, 1) + close(c) + @test first(iterate(c)) == 1 + @test isnothing(iterate(c)) end # PR #36641