如何处理光纤之外的光纤异常?

问题描述 投票:0回答:1

有时您需要使用未维护的,旧的,脏的,庞大的种类的库,这些库可能会对我们的程序造成危险。

是否有以安全方式执行此代码的最佳实践?

最近,我发现(可能是在我的知识和经验水平上)没有捕捉到异常。直到今天,我一直使用的通用做法是将代码包装到Fiber中,捕获内部异常并通过Channel发送出去。目前,这是行不通的(我无法在光纤中放入Yield或Proc)。

危险的lib可能看起来像是带有方法的普通类,该方法将Fiber.yield封装在Fiber中,以便立即交换执行到其他光纤。在现实生活中,这种光纤可能包含与IO一起使用的内部功能,没关系。

class LibDangerous
  def exec_remote
    spawn do
      raise IO::Error.new
    end
    Fiber.yield
  end
end

应该处理异常的包装器由begin ... rescue上的嵌套方法组成。我从顶层调用方法,从最后一个包装器方法调用,我返回lib方法,即使使用代码块begin ... rescue,该方法也总是使程序崩溃。

class Wrapper
  def capture
    begin
      yield self
    rescue
      puts "rescued from :capture"
    end
  end

  def guard
    begin
    capture do |this|
      yield this
    end
    rescue
      puts "rescued from :guard"
    end
  end

  def run
    begin
      yield LibDangerous.new
    rescue ex
      puts "rescued from :run"
    end
  end
end

这似乎是因为您需要在发生异常的同一级别上处理该异常,但是由于种种原因,我无法修改其他人的库的代码。

wrapper = Wrapper.new

result = wrapper.guard do |sandbox|
  begin
    sandbox.run do |library|
      library.exec_remote
    end
  rescue
    puts "rescued from top-level"
  end
end

轰! (this code on play.crystal-lang.org

Unhandled exception in spawn:  (IO::Error)
  from /eval:4:7 in '->'
  from /usr/lib/crystal/fiber.cr:255:3 in 'run'
  from /usr/lib/crystal/fiber.cr:92:34 in '->'
  from ???

可能由于交换可执行上下文而发生:我的代码和异常在不同的上下文中并且无法交互?如果卸下光纤,则照常捕获异常。

是否有可能在不修改原始库的情况下解决此问题?

有时您需要使用未维护,旧,脏,庞大且种类繁多的库,这些库可能会对我们的程序造成危险。是否存在以安全方式执行此代码的最佳实践? ...

exception crystal-lang fibers
1个回答
0
投票

否,如果不修补到原始错误代码中,您将无法处理。但是,Crystal的开放类系统使这一切在您看来始终是可能的,直到确定上游行为为止,您只需在代码中重新定义该方法即可。

[请注意,这只是处理操作失败这一事实的问题。如果您可以通过其他方式获得该信息,例如通过使用select超时等待结果,或者您根本不在乎操作是否成功,则唯一真正的问题是一些垃圾邮件。光纤不是主要光纤,崩溃不会破坏您的程序! (请参见https://play.crystal-lang.org/#/r/98da

© www.soinside.com 2019 - 2024. All rights reserved.