DEV Community

SEN LLC
SEN LLC

Posted on

A Searchable Linux/POSIX Signal Reference — Why SIGRTMIN Is 34, Not 32

A Searchable Linux/POSIX Signal Reference — Why SIGRTMIN Is 34, Not 32

kill -9 kills a process. kill -HUP tells nginx to reload its config. kill -TERM asks politely. But which number is which? What's the difference between SIGUSR1 and SIGUSR2? Why can you catch SIGTERM but not SIGKILL? This reference answers all of those, with bilingual descriptions and example kill commands.

Signals are one of those Unix primitives everyone uses but few people memorize. The man pages exist, but they're reference documentation, not fast lookup. A searchable, filtered, visual reference is faster — especially when you need to answer "what number is SIGUSR1 again?" in the middle of writing a service.

🔗 Live demo: https://sen.ltd/portfolio/linux-signals/
📦 GitHub: https://github.com/sen-ltd/linux-signals

Screenshot

Features:

  • 33 signals (POSIX + Linux extensions + RT range)
  • Search by name or number
  • Filter by default action (Term, Core, Ign, Stop, Cont)
  • Per-signal info: description, use cases, example command, catch/ignore/block flags
  • Bilingual Japanese / English descriptions
  • Dark / light theme
  • Zero dependencies, 41 tests

Why SIGRTMIN is 34 on Linux, not 32

The POSIX spec defines real-time signals starting at SIGRTMIN. On most Unix systems this is 32, but on Linux with glibc it's 34. Why?

glibc reserves signals 32 and 33 for NPTL (Native POSIX Thread Library) internal use — thread cancellation and setxid broadcasting. User code can't use them without breaking threading. So SIGRTMIN starts one past those: 34.

This is why you'll sometimes see "signal 34 received" in logs on Linux but never on macOS. Same code, different signal numbering.

Can't catch SIGKILL or SIGSTOP

The kernel guarantees that SIGKILL and SIGSTOP always take effect. You can't install a handler for them, can't ignore them, can't block them in a signal mask:

{
  number: 9,
  name: 'SIGKILL',
  canCatch: false,  // can't install a handler
  canIgnore: false, // SIG_IGN is refused
  canBlock: false,  // sigprocmask ignores it
  description: {
    en: 'Forceful termination. Cannot be caught, ignored, or blocked.',
  },
}
Enter fullscreen mode Exit fullscreen mode

This is by design: if any code could block SIGKILL, a runaway program could make itself unkillable. The kernel refuses to allow that.

The default action matrix

Each signal has a default action if the process doesn't install a handler:

Action Meaning
Term Terminate the process
Core Terminate + write a core dump
Ign Ignored (process continues)
Stop Stop the process (like Ctrl+Z)
Cont Resume a stopped process

Most terminal-related signals are Term (SIGHUP, SIGINT, SIGPIPE), most fatal fault signals are Core (SIGSEGV, SIGBUS, SIGFPE, SIGABRT), and the child-process signals are Ign (SIGCHLD default is to ignore, though many programs override).

Common use cases

Beyond "kill a process":

  • SIGHUP — nginx / Apache / sshd reload config. Originally meant "terminal hung up" but got repurposed for daemons that don't have controlling terminals.
  • SIGUSR1 / SIGUSR2 — Reserved for application-specific use. PostgreSQL uses SIGUSR1 for backend signaling, Apache for graceful restart.
  • SIGWINCH — Terminal window resized. Shells and TUI apps listen for this to redraw.
  • SIGCHLD — A child process changed state (died, stopped). Parent uses this to wait() without polling.

Each entry has a ja/en description and a real example command so you can copy-paste to try it.

Series

This is entry #62 in my 100+ public portfolio series.

Top comments (0)