ysbaddaden / execution_context

10 stars 2 forks source link

MT: invalid `fiber.@stack_top` in the default context #1

Closed ysbaddaden closed 8 months ago

ysbaddaden commented 8 months ago

The following program will crash during a GC collection because of an invalid #stack_top in a fiber stack (it's not within the fiber's stack top/bottom), but only when the default context is MT (set the -Dmt flag).

require "execution_context"

5000.times do |i|
  spawn { print "iteration #{i}\n" }
end
ysbaddaden commented 8 months ago

Creating another context and spawning into that context won't lead to a crash (whatever if the default context is MT or ST):

require "execution_context"
mtx = ExecutionContext::MultiThreaded.new("MTX", size: 9)

5000.times do |i|
  mtx.spawn { print "iteration #{i}\n" }
end

I can create 3 execution contexts and it still won't crash. But as soon as I start spawning inside the default context, then I immediately hit the invalid stack stop and the segfault.

ysbaddaden commented 8 months ago

Adding a Fiber.yield every N iterations in the loop will also avoid the segfault (tested with N <= 2000, with N = 4000 it will segfault):

require "execution_context"
mtx = ExecutionContext::MultiThreaded.new("MTX", size: 9)

5000.times do |i|
  mtx.spawn { print "iteration #{i}\n" }
  Fiber.yield if i % 2000 == 0
end
ysbaddaden commented 8 months ago

I enqueue the main fiber loop when hijacking the main thread, which means that any scheduler could steal and resume the run loop of the main thread's scheduler :facepalm: