A signal is an asynchronous notification delivered to a process, used for control such as termination, interrupts and timers. Handlers must be careful because a signal can arrive between any two instructions, and some signals cannot be caught at all.
Before you start
You should understand processes and basic control flow. This article covers common signals and handler safety.
Step-by-step walkthrough
Step 1: Catch SIGTERM for graceful shutdown
SIGTERM is the standard request to stop, sent by orchestrators before force-killing. Handling it lets the process stop accepting new work, drain in-flight requests and exit cleanly. Ignoring it forces the platform to escalate to a hard kill.
Step 2: Know what cannot be caught
SIGKILL cannot be caught or ignored, which is what makes it the guaranteed kill. SIGSTOP cannot be caught either. So graceful shutdown depends on SIGTERM; a process that ignores it will eventually be SIGKILLed with no chance to clean up.
Step 3: Keep handlers minimal and async-safe
A handler can run between instructions, so it may interrupt code that is partway through allocating or modifying shared state. Do only async-signal-safe work, such as setting a flag or writing to a pipe, and let the main loop perform the real cleanup. Heavy work in a handler risks deadlock and corruption.
Worked scenario
The process sets a flag on SIGTERM and shuts down in the main loop.
let shuttingDown = false;
process.on('SIGTERM', () => { shuttingDown = true; });
setInterval(() => { if (shuttingDown) process.exit(0); }, 100);Walk through the example
The handler does the minimum: it flips a flag. The main loop checks the flag and performs an orderly exit, so cleanup happens outside the signal context where it is safe. This is the pattern behind graceful shutdown in servers, though most runtimes provide a cleaner shutdown hook.
Common mistake
Doing complex work such as logging, locking or allocating inside the handler, which can deadlock if the signal interrupted the code holding the lock. Another is ignoring SIGTERM and being killed abruptly, losing in-flight work.
Verify the behavior
Send SIGTERM and confirm the process drains and exits with code 0. Send SIGKILL and confirm it cannot be caught. Log from the handler and observe the interrupted state if the handler does too much.
Interview exercise
Why must a signal handler avoid doing much work?
Answer and reasoning
Because the handler runs at an arbitrary point, possibly interrupting code that holds a lock or is mid-update of shared state. If the handler then calls the same lock or the same non-reentrant function, it can deadlock or corrupt data. Restricting the handler to async-signal-safe operations and deferring real work to the main flow avoids that.
Continue learning
Compare shutdown behavior in Graceful shutdown and IPC in IPC mechanisms. Read the Linux signal documentation and try the Operating systems interview questions.