【问题标题】:Ruby check whether program is currently being closedRuby 检查程序当前是否正在关闭
【发布时间】:2018-02-01 09:08:37
【问题描述】:

如何检查 Ruby 中的当前脚本是否正在关闭? 特别是,如果程序正在关闭,我想将@reconnect 设置为false,不再允许 web-socket 重新连接。我试过Signal.trap("TERM"),但它似乎不起作用。

@reconnect 是 WebsocketClient 类中的一个实例变量,我无法在类外的脚本中直接更改它。

class WebsocketClient
    def ws_closed(event)
      $logger.warn "WS CLOSED"
      Signal.trap("TERM") { 
        @stop = true
        @reconnect = false
      }

      unless $reauth
        if @stop
          EM.stop
        elsif @reconnect
          $logger.warn "Reconnecting..."
          EM.add_timer(@reconnect_after){ connect! }
        end
      end
    end
end

at_exit {
  $logger.fatal "Application terminated. Shutting down gracefully..."
  # ...
  # Do some exit work...
  # ...
  exit!
}

CTRL-C 输出

01-02-2018 12:00:54.59  WARN    > WS CLOSED
01-02-2018 12:00:54.595 WARN    > Reconnecting...
01-02-2018 12:00:54.596 FATAL   > Application terminated. Shutting down gracefully..

【问题讨论】:

    标签: ruby terminate


    【解决方案1】:

    见下文摘自我的回答Here,但似乎与您的问题比它当前所附的问题更相关:

    您最好的选择可能比信号捕获更容易一些。 Kernel Module 实际上为您提供了一个 #at_exit 方法,该方法将在程序实际退出之前执行。

    用法:(来自Kernel#at_exit Docs

    def do_at_exit(str1)
      at_exit { print str1 }
    end
    at_exit { puts "cruel world" }
    do_at_exit("goodbye ")
    exit
    

    “产生:”

    goodbye cruel world
    

    如您所见,您可以定义多个处理程序,这些处理程序将在程序退出时以相反的顺序执行。

    由于Kernel 包含在Object 中,因此您可以处理Object 的细节以及

    class People
      at_exit {puts "The #{self.name} have left"}
    end
    exit
    # The People have left
    

    甚至在实例上

    p = People.new
    p.send(:at_exit, &->{puts "We are leaving"})
    # We are leaving
    # The People have left
    

    另外,对于更具体的基于Object 的实现,您可以查看ObjectSpace.define_finalizer

    使用示例:

    class Person
      def self.finalize(name)
        proc {puts "Goodbye Cruel World -#{name}"}
      end 
      def initialize(name)
        @name = name
        ObjectSpace.define_finalizer(self, self.class.finalize(@name))
      end
    end
    

    用法:

    p = Person.new("engineersmnky")
    exit
    # Goodbye Cruel World -engineersmnky
    

    这可能不是你想要的,因为当Object 也被垃圾收集时它会触发(对于临时对象来说不是很好)但是如果你有应该存在于整个应用程序中的对象,它仍然可以类似地使用到 at_exit 。示例

    # requiring WeakRef to allow garbage collection 
    # See: https://ruby-doc.org/stdlib-2.3.3/libdoc/weakref/rdoc/WeakRef.html
    require 'weakref' # 
    p1 = Person.new("Engineer")
    p2 = Person.new("Engineer's Monkey")
    p2 = WeakRef.new(p2)
    GC.start # just for this example
    # Goodbye Cruel World -Engineer's Monkey
    #=> nil
    p2
    #=> WeakRef::RefError: Invalid Reference - probably recycled
    exit
    # Goodbye Cruel World -Engineer
    

    正如您所见,为 p2 定义的终结器被触发,因为 Person 已被 gc'd 但程序尚未退出。 p1 的终结器一直等到退出才触发,因为它在整个应用程序中保留了它的引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-13
      • 1970-01-01
      • 2012-01-13
      • 1970-01-01
      • 1970-01-01
      • 2017-07-23
      • 2011-06-30
      • 1970-01-01
      相关资源
      最近更新 更多