模块 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 传递语义在不同系统之间也可能有所不同;特别是信号传递可能并不总是可靠的。
公共类方法
源码
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;
}
返回信号名称映射到相应底层信号编号的列表。
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_signame(VALUE recv, VALUE signo)
{
const char *signame = signo2signm(NUM2INT(signo));
if (!signame) return Qnil;
return rb_str_new_cstr(signame);
}
将信号编号转换为信号名称。如果 signo 是无效的信号编号,则返回 nil。
Signal.trap("INT") { |signo| puts Signal.signame(signo) } Process.kill("INT", 0)
产生
INT
源码
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);
}
指定信号的处理方式。第一个参数是信号名称(例如 “SIGALRM”、“SIGUSR1” 等字符串)或信号编号。信号名称中的字符 “SIG” 可以省略。command 或 block 指定在信号引发时要运行的代码。如果 command 是字符串 “IGNORE” 或 “SIG_IGN”,则将忽略该信号。如果 command 是 “DEFAULT” 或 “SIG_DFL”,则将调用 Ruby 的默认处理程序。如果 command 是 “EXIT”,则脚本将因信号而终止。如果 command 是 “SYSTEM_DEFAULT”,则将调用操作系统的默认处理程序。否则,将运行给定的 command 或 block。特殊的信号名称 “EXIT” 或信号编号零将在程序终止之前被调用。trap 返回给定信号的先前处理程序。
Signal.trap(0, proc { puts "Terminating: #{$$}" }) Signal.trap("CLD") { puts "Child died" } fork && Process.wait
产生
Terminating: 27461 Child died Terminating: 27460