Understanding Signals
You have already seen processes being inspected and monitored. The next step is controlling them, but before using kill, pkill, or killall, it helps to understand what those commands actually send.
They send signals.
A signal is a small notification delivered by the kernel to a process. Different signals request different actions: some ask a process to terminate gracefully, some stop or continue it, and one can force it to disappear immediately.
What Is A Signal?
A signal is an asynchronous event sent to a process.
Conceptually:
Process
▲
│ signal
│
Kernel / another processFor example:
kill -TERM 1234does not mean “destroy PID 1234.”
It means:
Send signal
SIGTERMto PID 1234.
The process then receives that signal and, depending on the signal and its own signal-handling behavior, takes an appropriate action.
This distinction matters because kill is really a signal-sending command, despite its name.
Why Does Linux Use Signals?
Signals provide a simple mechanism for communicating important events to processes.
For example:
SIGTERM
→ Please terminate.
SIGKILL
→ Terminate immediately; no handling.
SIGSTOP
→ Stop executing.
SIGCONT
→ Continue a stopped process.
SIGHUP
→ Traditionally associated with a terminal disconnect;
commonly also used by services to request a reload.There are more signals, but these are enough to understand most everyday process management.
SIGTERM: Ask The Process To Stop
The signal you’ll generally want first when terminating a process is:
SIGTERMYou can send it explicitly:
kill -TERM 1234or using its signal number:
kill -15 1234The important idea is that SIGTERM is a request. A process can catch it and perform cleanup before exiting. For example, a server might receive SIGTERM and:
stop accepting new connections
↓
finish existing work
↓
close files
↓
flush data
↓
exitThis is why graceful termination is normally preferable to immediately killing a process.
A Process Can Handle SIGTERM
Unlike SIGKILL, a program can catch SIGTERM and decide what to do.
A simple Python example makes the idea concrete:
import os
import signal
import time
def handle_term(signum, frame):
print("Received SIGTERM, cleaning up...")
raise SystemExit
signal.signal(signal.SIGTERM, handle_term)
print("Running. PID:", os.getpid())
while True:
time.sleep(1)Run it:
python3 signal-demo.pyFrom another terminal, send:
kill -TERM <PID>The program receives the signal and runs its handler before exiting.
The point of this example isn’t Python signal programming. It demonstrates why
SIGTERMis useful: the application gets an opportunity to shut itself down properly.
SIGKILL: Force The Process To Die
SIGKILL is fundamentally different:
kill -KILL 1234or:
kill -9 1234The kernel terminates the process immediately. The process cannot catch, ignore, or handle SIGKILL. There is no graceful cleanup opportunity. That makes it powerful, but also dangerous.
The stackoverflow Q/A answers beautifully:
You cannot, at least not for the process being killed.
What you can do is arrange for the parent process to watch for the child process’s death, and act accordingly. Any decent process supervision system, such as daemontools, has such a facility built in.
The usual escalation is therefore:
SIGTERM
↓
wait
↓
check whether it exited
↓
SIGKILL only if necessaryWarning
kill -9 should not be your default way of stopping processes. It is the emergency option for a process that refuses to terminate normally or is otherwise stuck.
Why kill -9 Is So Common?
You will often see:
kill -9 <PID>used as if -9 simply means “kill harder.”
Technically, it means:
send signal number 9 = SIGKILLThe command isn’t asking the process to cooperate. The kernel terminates it directly.
This is useful when a process is genuinely refusing to terminate, but using it immediately can hide the actual reason a process isn’t shutting down cleanly.
SIGHUP: More Than A Terminal Hangup
Historically, SIGHUP means hangup.
It originated from terminal connections: when a terminal disappeared, processes associated with it could receive SIGHUP.
But many Unix/Linux services also use SIGHUP for:
reload configurationFor example, a daemon may document:
kill -HUP <PID>as a request to re-read its configuration without completely restarting.
This is application-specific behavior. SIGHUP does not universally mean “reload configuration.”
The important lesson is:
A signal has a defined operating-system meaning, but a program may implement its own useful response to a catchable signal.
SIGSTOP And SIGCONT
Signals aren’t only about termination.
SIGSTOP tells the kernel to stop a process:
kill -STOP 1234The process remains present, but it stops executing.
You can inspect its state with:
ps -p 1234 -o pid,stat,cmdThen resume it:
kill -CONT 1234Now the process can continue executing.
This is the same basic mechanism behind shell job control, which you’ll use later.
Some Signals Cannot Be Handled
Most signals can be caught, ignored, or handled by the process.
Two important exceptions are:
SIGKILL
SIGSTOPA process cannot catch or ignore either one.
This gives the kernel a guaranteed mechanism to:
terminate a processor:
stop a processeven if that process is badly behaved.
Signal Names And Numbers
Linux provides both names and numbers.
For example:
SIGHUP = 1
SIGKILL = 9
SIGTERM = 15
SIGSTOP = 19
SIGCONT = 18So these are equivalent:
kill -TERM 1234
kill -15 1234and:
kill -KILL 1234
kill -9 1234Using the signal name is often clearer because it communicates intent directly.
How Does kill Actually Fit In?
The relationship is:
kill
│
│ requests
▼
Kernel
│
│ delivers
▼
Signal
│
▼
ProcessSo:
kill -TERM 1234means:
Find PID 1234
↓
Ask the kernel to send SIGTERM
↓
Process receives SIGTERM
↓
Process handles it or follows its default actionkill does not directly reach into the process and terminate it. It asks the kernel to deliver a signal.
The Default Action Matters
Every signal has a default action defined by the operating system. For many signals, that action is termination. But a process can change its behavior for many signals by installing a signal handler or otherwise ignoring the signal.
For example:
SIGTERM
↓
default: terminate
↓
program may catch it
↓
program can perform cleanup
↓
program exitsWhereas:
SIGKILL
↓
kernel terminates process
↓
no handler
↓
no cleanup handlerThis difference is the reason SIGTERM and SIGKILL should not be treated as interchangeable.
What About A Zombie?
If a process is already a zombie, sending it:
kill -TERM <PID>doesn’t make the zombie disappear.
A zombie has already terminated. What remains is a small process-table entry containing its exit status until its parent collects it.
The parent needs to perform the appropriate wait() operation.
So:
Running process
↓ SIGTERM
Process exits
↓
Zombie temporarily exists
↓
Parent reaps it
↓
Zombie disappearsThis is another reason not to think of signals simply as “ways to delete processes.”
Choosing The Right Signal
| Signal | Meaning | Typical Use |
|---|---|---|
SIGTERM | Request termination | Normal shutdown |
SIGKILL | Immediate termination | Last resort |
SIGHUP | Hangup; application may use it for reload | Terminal/session events or service reloads |
SIGSTOP | Stop execution | Temporarily pause a process |
SIGCONT | Continue execution | Resume a stopped process |
You don’t need to memorize every signal.
You need to understand that signals are different requests, and the signal you choose determines how the process is expected to react.
A Safe Escalation Pattern
When a process needs to stop, think:
Do I know the correct PID?
↓
Send SIGTERM
↓
Wait and check
↓
Did it exit?
│
├── Yes → done
│
└── No
↓
Investigate why
↓
SIGKILL if genuinely necessaryThe important part is that SIGKILL comes after SIGTERM, not before it.
What You Should Remember
The most important distinction is simple:
SIGTERM
→ "Please shut down."
SIGKILL
→ "The kernel will terminate you now."
SIGSTOP
→ "Stop executing."
SIGCONT
→ "Continue executing."
SIGHUP
→ "Hangup" at the OS level;
applications may give it additional meaning such as reload.And remember what kill really does:
kill
↓
send a signal
↓
kernel
↓
processOnce you understand signals, commands such as kill, pkill, and killall become much easier to reason about. They are primarily different ways of selecting processes and sending signals to them.
What’s Next
The next lesson puts this knowledge into practice: safely killing processes with kill, pkill, and killall, including how to verify your target before sending a signal and how to avoid broad process-matching mistakes.