捕获 SIGINT 和清理的正确方法?

kre*_*eek 1 crystal-lang

编写一个 cli 工具,在启动时打开 OS X Web 代理,在关闭时我想再次关闭它。捕获 SIGINT 并执行应用程序清理的正确方法是什么?尝试了以下操作,它会跟踪消息但不运行系统命令或退出:

Signal::INT.trap do
  puts "trap"
  fork do
    system "networksetup -setwebproxystate Wi-Fi off"
  end
  exit
end
Run Code Online (Sandbox Code Playgroud)

此代码确实退出,但给出了“无效的内存访问”错误

at_exit do
  fork do
    system "networksetup -setwebproxystate Wi-Fi off"
  end
end

LibC.signal Signal::INT.value, ->(s : Int32) { exit }
Run Code Online (Sandbox Code Playgroud)
Invalid memory access (signal 10) at address 0x10d3a8e00
[0x10d029b4b] *CallStack::print_backtrace:Int32 +107
[0x10d0100d5] __crystal_sigfault_handler +181
[0x7fff6c5b3b3d] _sigtramp +29
Run Code Online (Sandbox Code Playgroud)

更新

这是使用的完整“应用程序” Signal::INT.trap,对我来说,它可以正确打开和关闭 OS X 代理设置,但循环将在中断信号后继续运行。

fork do
  system "networksetup -setwebproxy Wi-Fi  127.0.0.1 4242"
end

Signal::INT.trap do
  puts "trap"
  fork do
    system "networksetup -setwebproxystate Wi-Fi off"
  end
  exit
end

loop do
  sleep 1
  puts "foo"
end
Run Code Online (Sandbox Code Playgroud)

Ser*_*rov 6

你可以使用纤维吗?

spawn do
  system "networksetup -setwebproxy Wi-Fi  127.0.0.1 4242"
end

sleep 0.1

Signal::INT.trap do
  puts "trap"
  spawn do
    system "networksetup -setwebproxystate Wi-Fi off"
  end
  sleep 0.1
  exit
end

loop do
  sleep 1
  puts "foo"
end
Run Code Online (Sandbox Code Playgroud)