ch1 = Channel::Buffered(Int32).new(1)
ch2 = Channel::Buffered(Int32).new(1)
res = [] of Int32
spawn do
loop do
select
when x = ch1.receive
res << x
when y = ch2.receive
res << y
end
end
end
spawn do
3.times do |i|
select
when ch1.send(i)
when ch2.send(i)
end
end
end
Fiber.yield
p res
Invalid memory access (signal 11) at address 0x0
[4466037] *CallStack::print_backtrace:Int32 +117
[4444920] __crystal_sigfault_handler +56
[4758788] sigfault_handler +40
[140503573855408] ???
[0] ???
Did some playing around with this today. Doesn't seem to happen if case statement is changed to if, and doesn't seem to happen if case statement is changed to if/elsif (with or without plain else statement).
Fails right after a stack switch, according to gdb. I logged every crystal function, and couldn't get any closer to the exact error location.
I'm trying to get a copy of the generated code to see what the end product of the case statements look like (it appears they're turned into if/elsif), but beyond that, I'm out of ideas.
I'm not sure how helpful any this is, but the issue was marked help-wanted, so figured I'd comment.
i tried to debug this, but its quite hard, something breaks in coroutines switches.
Because there is a same fiber in ch1 and ch2, that could push the same fiber into scheduler twice. If you add such logger, then you will see that.
ch1 = Channel(Int32).new(1)
ch2 = Channel(Int32).new(1)
res = [] of Int32
class Scheduler
def self.log
LibC.printf "#{@@runnables}\n"
end
end
a = spawn do
loop do
select
when x = ch1.receive
res << x
when y = ch2.receive
res << y
end
LibC.printf "receive: "
Scheduler.log
end
end
b = spawn do
3.times do |i|
select
when ch1.send(i)
when ch2.send(i)
end
LibC.printf "send: "
Scheduler.log
end
end
p "receive fiber : #{a}"
p "send fiber : #{b}"
Fiber.yield
p res
"receive fiber : #<Fiber:0x1d37e00>"
"send fiber : #<Fiber:0x1d37d90>"
send: Deque{#<Fiber:0x1d37e00>}
send: Deque{#<Fiber:0x1d37e00>, #<Fiber:0x1d37e00>}
receive: Deque{#<Fiber:0x1d37e00>, #<Fiber:0x1d37d90>}
receive: Deque{#<Fiber:0x1d37e00>, #<Fiber:0x1d37d90>, #<Fiber:0x1d37d90>}
send: Deque{#<Fiber:0x1d37d90>, #<Fiber:0x1d37e00>}
Invalid memory access (signal 11) at address 0x0
[4413221] *CallStack::print_backtrace:Int32 +117
[4391592] __crystal_sigfault_handler +56
[4608565] sigfault_handler +40
[140189768220800] ???
[0] ???
After third sending, the fiber are going to the end and Scheduler will resume the fiber again. That's why it crashed.
This issue appears to persist with 0.23.1 https://carc.in/#/r/2imm
An effort to rewrite the Channel implementation has been undertaken in #3912, and also appears to have not much feedback.
It doesn't segfault anymore, but still crashes at runtime: https://carc.in/#/r/7gtb
Somebody wants to try it against #8112? :)
I tried it with #8112 and it works fine 馃帀
Closed by #8112
Please reopen if the issue remains.
Most helpful comment
I tried it with #8112 and it works fine 馃帀