模块 Signal
许多操作系统允许向正在运行的进程发送信号。一些信号对进程有定义的效果,而另一些信号可以在代码级别被捕获并进行处理。例如,您的进程可以捕获 USR1 信号并使用它来切换调试,并可以使用 TERM 来启动受控关闭。
pid = fork do Signal.trap("USR1") do $debug = !$debug puts "Debug now: #$debug" end Signal.trap("TERM") do puts "Terminating..." shutdown() end # . . . do some work . . . end Process.detach(pid) # Controlling program: Process.kill("USR1", pid) # ... Process.kill("USR1", pid) # ... Process.kill("TERM", pid)
产生
Debug now: true Debug now: false Terminating...
可用信号名称及其解释的列表取决于系统。 Signal
传递语义也可能因系统而异;特别是信号传递可能并不总是可靠的。
公共类方法
list → a_hash 点击切换源代码
返回一个信号名称列表,映射到相应的底层信号编号。
Signal.list #=> {"EXIT"=>0, "HUP"=>1, "INT"=>2, "QUIT"=>3, "ILL"=>4, "TRAP"=>5, "IOT"=>6, "ABRT"=>6, "FPE"=>8, "KILL"=>9, "BUS"=>7, "SEGV"=>11, "SYS"=>31, "PIPE"=>13, "ALRM"=>14, "TERM"=>15, "URG"=>23, "STOP"=>19, "TSTP"=>20, "CONT"=>18, "CHLD"=>17, "CLD"=>17, "TTIN"=>21, "TTOU"=>22, "IO"=>29, "XCPU"=>24, "XFSZ"=>25, "VTALRM"=>26, "PROF"=>27, "WINCH"=>28, "USR1"=>10, "USR2"=>12, "PWR"=>30, "POLL"=>29}
static VALUE sig_list(VALUE _) { VALUE h = rb_hash_new(); const struct signals *sigs; FOREACH_SIGNAL(sigs, 0) { rb_hash_aset(h, rb_fstring_cstr(sigs->signm), INT2FIX(sigs->signo)); } return h; }
signame(signo) → string or nil 点击切换源代码
将信号编号转换为信号名称。如果 signo 是无效的信号编号,则返回 nil
。
Signal.trap("INT") { |signo| puts Signal.signame(signo) } Process.kill("INT", 0)
产生
INT
static VALUE sig_signame(VALUE recv, VALUE signo) { const char *signame = signo2signm(NUM2INT(signo)); if (!signame) return Qnil; return rb_str_new_cstr(signame); }
trap( signal, command ) → obj 点击切换源代码
trap( signal ) {| | block } → obj
指定信号的处理方式。第一个参数是信号名称(一个字符串,例如“SIGALRM”、“SIGUSR1”等)或信号编号。信号名称中的“SIG”字符可以省略。命令或块指定在信号被触发时要运行的代码。如果命令是字符串“IGNORE”或“SIG_IGN”,则忽略该信号。如果命令是“DEFAULT”或“SIG_DFL”,则将调用 Ruby 的默认处理程序。如果命令是“EXIT”,则脚本将被信号终止。如果命令是“SYSTEM_DEFAULT”,则将调用操作系统的默认处理程序。否则,将运行给定的命令或块。特殊的信号名称“EXIT”或信号编号零将在程序终止之前被调用。trap 返回给定信号的先前处理程序。
Signal.trap(0, proc { puts "Terminating: #{$$}" }) Signal.trap("CLD") { puts "Child died" } fork && Process.wait
产生
Terminating: 27461 Child died Terminating: 27460
static VALUE sig_trap(int argc, VALUE *argv, VALUE _) { int sig; sighandler_t func; VALUE cmd; rb_check_arity(argc, 1, 2); sig = trap_signm(argv[0]); if (reserved_signal_p(sig)) { const char *name = signo2signm(sig); if (name) rb_raise(rb_eArgError, "can't trap reserved signal: SIG%s", name); else rb_raise(rb_eArgError, "can't trap reserved signal: %d", sig); } if (argc == 1) { cmd = rb_block_proc(); func = sighandler; } else { cmd = argv[1]; func = trap_handler(&cmd, sig); } if (rb_obj_is_proc(cmd) && !rb_ractor_main_p() && !rb_ractor_shareable_p(cmd)) { cmd = rb_proc_isolate(cmd); } return trap(sig, func, cmd); }