Ruby检查程序当前是否正在关闭

tf7tbtn2  于 2023-05-17  发布在  Ruby
关注(0)|答案(1)|浏览(116)

如何检查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..
xxb16uws

xxb16uws1#

见下面从我的答案在这里,但似乎更相关的问题比一个它目前附加到:
你最好的办法可能比信号捕获容易一点。KernelModule实际上为您提供了一个#at_exit方法,该方法将在程序实际退出之前执行。
用法:(来自Kernel#at_exit文档)

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中,因此您可以像处理

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的终结器一直等到exit才触发,因为它在整个应用程序中保留了自己的引用。

相关问题