What a signal is
A signal is a tiny integer notification that the kernel delivers to a process. The process can handle the signal (install a handler), ignore it, or do nothing. In that last case the default action runs, and the default is usually "terminate".
The most important signals
| signal | # | default action | when it is sent |
|---|---|---|---|
| SIGHUP | 1 | terminate | TTY closed; for services, "reload config" |
| SIGINT | 2 | terminate | Ctrl+C in a terminal |
| SIGQUIT | 3 | core dump | Ctrl+\ |
| SIGKILL | 9 | terminate | direct kill, cannot be handled or ignored |
| SIGTERM | 15 | terminate | the standard "please shut down" |
| SIGSTOP | 19 | stop | pause the process, cannot be handled |
| SIGCONT | 18 | continue | resume a stopped process |
| SIGUSR1/2 | 10/12 | terminate | for the application; often used to give a command without a restart |
| SIGPIPE | 13 | terminate | you write to a pipe whose reader has closed |
| SIGCHLD | 17 | ignore | a child process exited, so you need wait() |
| SIGSEGV | 11 | core dump | access to invalid memory |
The correct shutdown pattern
Send TERM first, give it a few seconds for a graceful exit, then KILL:
kill <pid> # send TERM
sleep 5
kill -KILL <pid> # if still alive, finish it off
A well-behaved service handles TERM by closing its listening sockets, finishing
the current requests, flushing buffers, and saving state. A plain kill -9 tears
all of that apart: lost transactions, corrupted files, stuck DB locks.
Which signal to use when
- TERM is the ordinary "stop", your default
- KILL only when TERM did not work
- HUP for daemons means "reload config" (nginx, syslog)
- USR1/2 can mean anything the application defines: for example, nginx USR1 is log rotation
- STOP/CONT pause and resume a process, useful for long-running batch jobs
Where all this is configured
In bash, signals are overridden through trap:
trap 'echo got SIGINT; exit 1' INT
trap 'cleanup; exit' EXIT