3

I'm using Fibers to handle scheduling between different chunks of code, and this has proven to be massively simpler than trying to manage Threads since my use case is fairly simple (and involves only running one script at a time). Unfortunately I need the ability to occasionally "kill" a Fiber, but it seems there is nothing in Fiber that is analogous to Thread.kill

My Fibers are just running a user supplied template, so it would be overly unwieldy to put in numerous "have I been killed and if so I need to return all the way to the top level". And also 'exit' in a Fiber just calls exit on the entire ruby interpreter.

Is there some way to either kill a fiber or have a fiber completely 'exit' from it's work?

Failing that (and perhaps this is another question, but it demonstrates why I'm looking for Fiber.kill) - I'm also looking into using Threads to basically implement Fibers (with the additional "kill" ability), but I don't see any way to do a thr.run or a thr.join that will wait until the thread has hit Thread.stop, and then allow me to take control again in my main scheduler, so Threads don't seem to be able to solve my situation either - short of having a main thread that just starts a thread and sits and polls for the thread to have finished it's segment of work, which seems messy and troubling at best.

  • Fibers may not be the right approach for what you're trying to do. Fibers aren't scheduled by the interpreter or pre-empted,; because they self-manage, the way to exit is to yield or allow the block to complete. – sj95126 Sep 11 '21 at 03:46
  • I don't actually want something that is scheduled by the interpreter or preempted. In every way, Fibers are perfect for what I want, except for the fact that they don't have a way to be terminated. – David Ljung Madison Stellar Sep 11 '21 at 04:13
  • That's the nature of fibers - because they manage themselves, there's no way to terminate them externally. You'll have to have a way for the fiber to detect that it should end and leave the block. – sj95126 Sep 11 '21 at 04:21

1 Answers1

2

I'm struggling to understand how yield/resume isn't able to solve your problem - but when the fibre has yielded you can abort it using raise Fiber#raise


def build_fibre
  Fiber.new do |first|
    puts 'doing work'
    3.times { Fiber.yield false }

    puts 'finished work'
    true
  rescue
    puts 'aborted'
  end
end


fiber1 = build_fibre
fiber1.resume

# Raise an exception at the `yield` call
fiber1.raise

fiber2 = build_fibre
loop do
  puts 'waiting'
  break if fiber2.resume
end

puts 'finished'
roo
  • 7,106
  • 8
  • 39
  • 45
  • Note that ```Fiber#raise``` was added in v2.7 and doesn't work in older versions. – sj95126 Sep 11 '21 at 13:49
  • Brilliant - I hadn't considered sending an exception to the Fiber to kill it. That solves my problem. I can't use yield/resume because all of the fiber management is handled by library calls, and those calls have the ability to terminate the fiber - so they need a way to be able to exit the fiber completely but from inside of a call.. So catching a specific exception is the answer. – David Ljung Madison Stellar Sep 13 '21 at 20:05