Sha256: 915ec966e1504fecb9a9fc9bcbe68cdc47cb900aa573a48fba323d01edb7a95d

Contents?: true

Size: 1.57 KB

Versions: 4

Compression:

Stored size: 1.57 KB

Contents

# frozen_string_literal: true

require 'fiber'

# This is an experiment to see if we could provide better backtraces for
# exceptions raised in fibers. Our approach is to monkey-patch Fiber.new so as
# to keep track of the caller stack trace and calling fiber. We also
# monkey-patch Exception#backtrace to calculate the full backtrace based on the
# fiber in which the exception was raised. The benefit of this approach is that
# there's no need to sanitize the backtrace (remove stack frames related to the
# backtrace calculation).
class Fiber
  attr_writer :__calling_fiber__, :__caller__

  class << self
    alias_method :orig_new, :new
    def new(&block)
      calling_fiber = Fiber.current
      fiber_caller = caller
      orig_new(&block).tap do |f|
        f.__calling_fiber__ = calling_fiber
        f.__caller__ = fiber_caller
      end
    end
  end

  def caller
    @__caller__ ||= []
    if @__calling_fiber__
      @__caller__ + @__calling_fiber__.caller
    else
      @__caller__
    end
  end
end

class Exception
  alias_method :orig_initialize, :initialize

  def initialize(*args)
    @__raising_fiber__ = Fiber.current
    orig_initialize(*args)
  end

  alias_method :orig_backtrace, :backtrace
  def backtrace
    unless @backtrace_called
      @backtrace_called = true
      return orig_backtrace
    end

    if @__raising_fiber__
      backtrace = orig_backtrace || []
      backtrace + @__raising_fiber__.caller
    else
      orig_backtrace
    end
  end
end

def foo
  Fiber.new do
    bar
  end.resume
end

def bar
  Fiber.new do
    raise 'baz'
  end.resume
end

foo

Version data entries

4 entries across 4 versions & 1 rubygems

Version Path
polyphony-0.23 examples/core/fiber_error_with_backtrace.rb
polyphony-0.22 examples/core/fiber_error_with_backtrace.rb
polyphony-0.21 examples/core/fiber_error_with_backtrace.rb
polyphony-0.20 examples/core/fiber_error_with_backtrace.rb