Recently, Eonil asked the question about keyboard combinations in Mac OS X that let him stop programs in a terminal window:
I’m using Mac OS X Terminal. And I use Ctrl+Z or Ctrl+C to stop some programs. But I realized that I don’t know exactly what they’re doing. What are they and what’s the difference between them?
This received quite a bit of interest, and while Mark’s answer is spot-on, we thought we’d take a closer look at what signals are, what they are used for and how you (as a user) might be using them.
Just what are signals?
Signals are a fairly basic form of inter-processes communication. They allow a process to send a simple notification to another process, and then continue its own business.
Once a signal is sent to a process, the operating system will interrupt the receiving process’s flow of execution at the next available opportunity and its execution will then jump to the relevant handler for the signal received. A program may register its own handlers for specific signal types, register that it will ignore specific signal types, or otherwise the default handlers will be called for the type of signal received (and the default might be to ignore the signal).
If the handler function doesn’t terminate the process, then once it is complete the process’s execution should return to the point of interruption, and continue as normal (but with any modifications the handler may have made to the process’s state).
They are supported on POSIX-compliant systems, and while Windows has a similar concept, it has much more limited scope and a different set of signal types. From here on, unless I explicitly mention Windows you can assume it is excluded from the topic at hand.
Signals can be triggered by several methods, but many of these are more of interest to a programmer, so we’ll just take a look at those methods a user may commonly trigger:
OK, and what are they used for?
Well, the most obvious use is that the user can use signals to request a program to do something (usually terminate), and we’ll cover that in a moment.
Programs can use signals for managing state. For example when a child process ends the parent is sent a
SIGCHLD, by default this is ignored, but for a process that manages multiple worker processes this would provide valuable information. Alternatively, a parent could send signals to it’s children to request shutdown or to ask for a status update, etc.
Finally, many signals are raised by the OS to report to the process when a serious error has occurred, all of which will terminate a process by default (and only some of which can be caught by the process safely), here’s a few examples:
SIGBUSis raised when a process causes a bus error, usually by attempting to use an invalid memory location.
SIGFPEor “floating point exception” is raised when an arithmetic calculation results in an error, such as divide by zero or under/overflow. This doesn’t just apply to just floating point arithmetic, but the name is kept for backwards compatibility.
SIGILLor “illegal instruction” is raised when attempting to use an instruction that isn’t recognised or isn’t permitted. This could be caused by a corrupt program, or attempting to use instructions that require special privileges without said privileges.
SIGPIPEis raised when a process attempts to write to a pipe that doesn’t have a process connected at the other end (either the other process has gone, or was never there to start with).
Keyboard Combinations for your Terminal
If you’re running a program from a terminal or command window on a POSIX or Windows system then there are a few keyboard combinations that can be used to send a signal directly to the foreground process in that window. While these are the most common combinations, please note that they may be different on some systems (especially since
stty is available to remap them).
Ctrl + C
On both POSIX and Windows this sends a
SIGINT (aka “Interrupt”) signal. By default this will terminate the process. But, a program may provide its own handler, which should do some clean up work and then return control to you (and it might not actually terminate – imagine software doing a massive, slow, calculation; a
SIGINT might request that it return the best result so far and then keep going, for example).
Ctrl + Z
On a POSIX system, this sends a
SIGTSTP signal, with
TSTP meaning “tty stop” or “teletypewriter stop”, where teletypewriter is a outdated name used to refer to a computer terminal.
This signal should suspend the process, stopping its execution and moving it to the background, allowing you to continue using the terminal.
Once suspended, you can use the
fg command to reactivate the process in the foreground, or
bg to reactivate the process in the background – the latter allowing you to continue using the terminal while the process continues to run (although you can’t send the process any keyboard input and the output will still appear on the parent terminal).
jobs program provides a handy way to see every process you have suspended from the current terminal instance, and obviously, you can use
ps to get information on all processes, if necessary. A suspended process can still receive signals – so you can use
kill if you want to get rid of it without having to start it up.
On a Windows system, this doesn’t send a signal, but instead produces an single End-Of-File character (or EOF control code), which if you’re providing input to a process is likely to make it assume the input is finished (and thus finish) but otherwise is unlikely to have an effect.
On POSIX systems this sends
SIGQUIT (aka “Quit”) to request the process terminates and performs a core dump, which could be handy if you want to debug the program.
Ctrl + Break
On a Windows system this sends a (non-POSIX)
SIGBREAK signal, this has a very similar effect to
SIGINT on Windows, except that a program cannot entirely ignore it – Ctrl+C can be read as input or ignored entirely, but Ctrl+Break is always a signal. Admittedly, this doesn’t stop the process from then handling the signal without terminating, but this is more likely to be effective than Ctrl+C.
killing any process you like
kill is a command available on POSIX systems that can be used to send a signal of your choice to a process. The basic usage is either
kill <PID> or
kill -<signal> <PID>, if you don’t specify a signal then the default (
SIGTERM) is used.
You can of course send any signal you like to a process, you can even select signals by number so you can even send signals that don’t actually mean anything. And obviously sending any of the error signals (like say
SIGFPE discussed above) is likely to upset your processes.
Here’s a few signals that you might find useful to send to processes, just remember that you shouldn’t include the
SIG when using these with the
This is the default, and requests the process to terminate.
This signal will cause a process to terminate immediately (with one exception, which I’ll get to in a moment) because it cannot be caught or ignored by a process. This makes it very useful to removing almost any process that is stuck or that ignoring the other signals normally used to terminate a process. But, remember that it provides the process with no opportunity to clean up after itself, so you should avoid using this as a first choice – save it for when a process doesn’t respond to
The exception is a process that is in “uninterruptible sleep”, which usually occurs when a process is blocking for some kind of I/O operation that never arrives. A process in this state will not receive any signals (including
SIGKILL!) until it wakes up. If you use
ps -l, processes that are uninterruptedly asleep will be marked with code “D”. From what I’ve managed to find out the only reliable way to fix a process in this state is to reboot (or find some way to wake it up, but knowing what the process is stuck waiting for is not a trivial task).
This is very similar to the
SIGTSTP signal that Ctrl+Z sends, in that it also suspends the program until you tell it to continue, but (like
SIGKILL) it cannot be caught or ignored!
If the process is stopped (via
SIGTSTP) then this will resume it.
kill using Windows?
Well yes and no.
Windows comes with
taskkill, which has roughly the results as using the “End Task” and “End Process” functionality of Task Manager. It doesn’t, however, provide the functionality to send arbitrary signals (because Windows doesn’t really have them), so it can’t be used for much else, that said POSIX
kill can’t be used for a lot of things either, but hopefully you see what I mean.