A custom iterator throws the subject error every time I run the code below. It does so when run plain or under VSCode, and it does so with one thread or many. It is odd for several reasons:
- The line throwing the error is immediately preceded by a test for the channel being open.
- There is only one producer and one consumer on the channel.
- The problem does not occur when run under the debugger (at least for some versions of the code).
- A slight change in seemingly irrelevant code eliminates the problem (even further below).
Can anyone explain to me what is going on, or how I can avoid the problem? Does this look like a julia
bug?
I think the problem arises after successful iteration of all possibilities; given the different behavior under the debugger that isn’t a very firm conclusion.
Running julia 1.8.5 on MS-Windows Server 2019.
In case you’re wondering, my motivation was to do something like Python
’s yield
, which seems to require a Channel
in julia
.
My apologies for the length; this is what I ended up with building up from simpler code that didn’t exhibit the error.
Code to Generate Error
struct TestR
requests
end
function test_helper(chan::Channel, t::TestR)
for (ctor, λs) in t.requests
for λ in λs
put!(chan, λ)
end
end
end
function Base.iterate(t::TestR)
f(c::Channel) = test_helper(c, t)
chan = Channel(f)
return Base.iterate(t, chan)
end
function Base.iterate(t::TestR, chan)
if !isopen(chan)
return nothing
end
x = take!(chan) # error thrown from here
if isnothing(x)
return nothing
end
return (x, chan)
end
function Base.length(t::TestR)
sum(length(λs) for (_, λs) in t.requests)
end
function outside(t::TestR)
r = Array{String}(undef, length(t))
i = 1
for x in t
r[i] = string(x)
end
return r
end
myt = TestR([(exp, (1.4,)), ])
println(outside(myt))
Error Message
PS C:\Users\rdboylan\Documents\BP\MSEP\src> julia --project -t4 -- test3.jl
ERROR: LoadError: InvalidStateException: Channel is closed.
Stacktrace:
[1] try_yieldto(undo::typeof(Base.ensure_rescheduled))
@ Base .\task.jl:871
[2] wait()
@ Base .\task.jl:931
[3] wait(c::Base.GenericCondition{ReentrantLock})
@ Base .\condition.jl:124
[4] take_unbuffered(c::Channel{Any})
@ Base .\channels.jl:433
[5] take!
@ .\channels.jl:410 [inlined]
[6] iterate
@ C:\Users\rdboylan\Documents\BP\MSEP\src\test3.jl:25 [inlined]
[7] outside(t::TestR)
@ Main C:\Users\rdboylan\Documents\BP\MSEP\src\test3.jl:41
[8] top-level scope
@ C:\Users\rdboylan\Documents\BP\MSEP\src\test3.jl:46
in expression starting at C:\Users\rdboylan\Documents\BP\MSEP\src\test3.jl:46
Error-free Code
Same as other code except
function outside(t::TestR)
r = Array{String}(undef, length(t))
for x in t
print(x,", ")
end
print("\n")
end