1. Technology
You can opt-out at any time. Please refer to our privacy policy for contact information.

Signals

By

Signals are a primitive way for operating systems to communicate with processes (or in some cases processes to communicate with other processes). They're most often used by the operating system to terminate processes and allow them to clean up before they're taken down, but they have other uses as well.

If your operating system supports signals (and generally those are the UNIX-like operating systems like Linux or OS X), then you can likely handle any signals sent to your Ruby programs. But first, let's look at the four most commonly used signals.

  • SIGINT - This is most often sent to your program when Ctrl-C has been pressed. It signifies that someone wishes for your program to be terminated. It doesn't mean, however, that your program must terminate immediately. You have time to close your files, send some network messages, etc before everything shuts down. Or you could ignore the signal and prevent your program from being closed normally. If you don't catch the signal, Ruby will raise an Interrupt exception.
  • SIGTERM - This is sent by the OS when someone wants to kill your program. By using the "kill" command you by default send SIGTERM. You can also ignore this signal and not shut down. While that sounds a bit rude, if you're in the middle of a database transaction or something it might not be a good idea to terminate the program even though you were asked to terminate. If something really wants to kill your program no matter what, it can send SIGKILL instead.
  • SIGKILL - This signal means business. The operating system is terminating your program. Do not pass go, do not collect $200. There is no chance for a signal handler to be run, and no atexit blocks will be run. A sigkill is a "kill -9" or a Ctrl-\ (control backslash), and this will almost always successfully terminate a program. This signal cannot be ignored
  • SIGUSR1 and SIGUSR2 - These are user-defined signals used for primitive interprocess communication. If you don't explicitly handle them, these signals don't do anything. They can be useful to signal your program to prepare for shutdown, or to enable debugging mode, or to turn on a remote debugging console, or the like.

     

Resist Death

As an example, the following program tries to resist all attempts to kill it. It catches SIGINT and SIGTERM and simply taunts you on STDIO. However, if you send it SIGKILL it will proclaim its death and the OS will kill it off. Remember that SIGINT and SIGTERM normally kill the program, if you have signal handlers for these signals and you actually do wish to kill the program, you'll have to manually exit the programmer at the end of the signal handler.


#!/usr/bin/env ruby

Signal.trap("INT") do
  puts "I'm afraid I can't let you do that, Dave."
end

Signal.trap("TERM") do
  puts "You can't catch me, I'm the gingerbread man!"
end

puts "My pid is #{Process.pid}"
gets while true

As you can see, this is all very straightforward. The program prints its process ID when it first starts which allows you to easily use the kill command (on Linux) to send signals to the program. So start it up and try Ctrl-C or kill -INT [pid] the program will respond with I'm afraid I can't let you do that, Dave and not quit. If you try a normal kill [pid], which send SIGTERM, it will respond with You can't catch me, I'm the gingerbread man!. And finally if you kill -9 [pid] or kill -KILL [pid] the program will just terminate.

So what are these used for? The answer is "not much." If your program is in the middle of sending an important message, it might want to ignore SIGINT and SIGTERM signals and close down later. And you can probably think of some uses for SIGUSR1 and SIGUSR2, but there are other ways to do that as well. These won't be something you use every day, but I'm sure you'll find a use for them somewhere.

  1. About.com
  2. Technology
  3. Ruby
  4. Advanced Ruby
  5. Signals

©2014 About.com. All rights reserved.