Module: Signal
- Defined in:
- signal.c
Overview
Many operating systems allow signals to be sent to running processes. Some signals have a defined effect on the process, while others may be trapped at the code level and acted upon. For example, your process may trap the USR1 signal and use it to toggle debugging, and may use TERM to initiate a controlled shutdown.
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)
produces:
Debug now: true
Debug now: false
Terminating...
The list of available signal names and their interpretation is system dependent. Signal delivery semantics may also vary between systems; in particular signal delivery may not always be reliable.
Class Method Summary collapse
-
.list ⇒ Hash
Returns a list of signal names mapped to the corresponding underlying signal numbers.
-
.trap ⇒ Object
Specifies the handling of signals.
Instance Method Summary collapse
-
#initialize ⇒ Object
Construct a new SignalException object.
-
#signo ⇒ Numeric
Returns a signal number.
Class Method Details
.list ⇒ Hash
Returns a list of signal names mapped to the corresponding underlying signal numbers.
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}
|
# File 'signal.c'
/*
* call-seq:
* Signal.list -> a_hash
*
* Returns a list of signal names mapped to the corresponding
* underlying signal numbers.
*
* 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(void)
{
VALUE h = rb_hash_new();
const struct signals *sigs;
for (sigs = siglist; sigs->signm; sigs++) {
rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
}
return h;
}
|
.trap(signal, command) ⇒ Object .trap(signal) {|| ... } ⇒ Object
Specifies the handling of signals. The first parameter is a signal name (a string such as "SIGALRM", "SIGUSR1", and so on) or a signal number. The characters "SIG" may be omitted from the signal name. The command or block specifies code to be run when the signal is raised. If the command is the string "IGNORE" or "SIG_IGN", the signal will be ignored. If the command is "DEFAULT" or "SIG_DFL", the Ruby's default handler will be invoked. If the command is "EXIT", the script will be terminated by the signal. If the command is "SYSTEM_DEFAULT", the operating system's default handler will be invoked. Otherwise, the given command or block will be run. The special signal name "EXIT" or signal number zero will be invoked just prior to program termination. trap returns the previous handler for the given signal.
Signal.trap(0, proc { puts "Terminating: #{$$}" })
Signal.trap("CLD") { puts "Child died" }
fork && Process.wait
produces:
Terminating: 27461
Child died
Terminating: 27460
|
# File 'signal.c'
/*
* call-seq:
* Signal.trap( signal, command ) -> obj
* Signal.trap( signal ) {| | block } -> obj
*
* Specifies the handling of signals. The first parameter is a signal
* name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
* signal number. The characters ``SIG'' may be omitted from the
* signal name. The command or block specifies code to be run when the
* signal is raised.
* If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
* will be ignored.
* If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
* will be invoked.
* If the command is ``EXIT'', the script will be terminated by the signal.
* If the command is ``SYSTEM_DEFAULT'', the operating system's default
* handler will be invoked.
* Otherwise, the given command or block will be run.
* The special signal name ``EXIT'' or signal number zero will be
* invoked just prior to program termination.
* trap returns the previous handler for the given signal.
*
* Signal.trap(0, proc { puts "Terminating: #{$$}" })
* Signal.trap("CLD") { puts "Child died" }
* fork && Process.wait
*
* produces:
* Terminating: 27461
* Child died
* Terminating: 27460
*/
static VALUE
sig_trap(int argc, VALUE *argv)
{
struct trap_arg arg;
rb_secure(2);
if (argc < 1 || argc > 2) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
}
arg.sig = trap_signm(argv[0]);
if (argc == 1) {
arg.cmd = rb_block_proc();
arg.func = sighandler;
}
else {
arg.cmd = argv[1];
arg.func = trap_handler(&arg.cmd, arg.sig);
}
if (OBJ_TAINTED(arg.cmd)) {
rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
}
#if USE_TRAP_MASK
/* disable interrupt */
sigfillset(&arg.mask);
pthread_sigmask(SIG_BLOCK, &arg.mask, &arg.mask);
return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
#else
return trap(&arg);
#endif
}
|
Instance Method Details
#new(sig_name) ⇒ Object #new(sig_number[, name]) ⇒ Object
Construct a new SignalException object. sig_name
should be a known
signal name.
|
# File 'signal.c'
/*
* call-seq:
* SignalException.new(sig_name) -> signal_exception
* SignalException.new(sig_number [, name]) -> signal_exception
*
* Construct a new SignalException object. +sig_name+ should be a known
* signal name.
*/
static VALUE
esignal_init(int argc, VALUE *argv, VALUE self)
{
int argnum = 1;
VALUE sig = Qnil;
int signo;
const char *signm;
if (argc > 0) {
sig = rb_check_to_integer(argv[0], "to_int");
if (!NIL_P(sig)) argnum = 2;
else sig = argv[0];
}
if (argc < 1 || argnum < argc) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
argc, argnum);
}
if (argnum == 2) {
signo = NUM2INT(sig);
if (signo < 0 || signo > NSIG) {
rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
}
if (argc > 1) {
sig = argv[1];
}
else {
signm = signo2signm(signo);
if (signm) {
sig = rb_sprintf("SIG%s", signm);
}
else {
sig = rb_sprintf("SIG%u", signo);
}
}
}
else {
signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig);
if (strncmp(signm, "SIG", 3) == 0) signm += 3;
signo = signm2signo(signm);
if (!signo) {
rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
}
sig = rb_sprintf("SIG%s", signm);
}
rb_call_super(1, &sig);
rb_iv_set(self, "signo", INT2NUM(signo));
return self;
}
|
#signo ⇒ Numeric
Returns a signal number.
|
# File 'signal.c'
/*
* call-seq:
* signal_exception.signo -> num
*
* Returns a signal number.
*/
static VALUE
esignal_signo(VALUE self)
{
return rb_iv_get(self, "signo");
}
|