1.Processes, PIDs, signals and threads
A **process** is one running program with its own memory. Its **PID** is the number the kernel gives it, and the number every tool asks you for. A **signal** is a one-byte message you send to a process — `SIGTERM` asks it to stop, `SIGKILL` makes the kernel stop it. A **thread** runs inside a process and shares that process's memory, which is why threads are cheaper and why one thread's crash can take the whole process with it.
Key features
- One process = one memory space; workers share nothing but the socket
- A PID is kernel-assigned, reused after exit, and different after every restart
- SIGTERM (15) asks; SIGKILL (9) "cannot be caught, blocked, or ignored"
- A KILLed worker loses its in-flight requests — no cleanup code runs at all
- SIGHUP is the conventional "reload config"; gunicorn respawns workers on it
- Threads share memory and, under the GIL, buy I/O concurrency — not CPU parallelism
The signals worth knowing, and what gunicorn does with each
Process or thread — what you actually get
- A tree diagram. At the top, systemd, PID 1, is the parent of the gunicorn master process, PID 4812.
- The gunicorn master has three children drawn below it: worker processes with PIDs 4813, 4814 and 4815. Each worker box notes that it holds its own memory and its own database connection.
- A separate branch on the right shows a Celery master, PID 5001, with one worker child, PID 5002, drawn to show that background work is its own process tree.
- An arrow labelled SIGTERM points at the gunicorn master only, with a note that the master forwards a graceful stop to its workers.
- A red note states that SIGKILL sent to a worker loses that worker in-flight requests, because no cleanup code runs.
Command
kill -TERM <pid> # ask; the process may clean up
kill -KILL <pid> # the kernel stops it; nothing runs, nothing is savedA Django deployment is a process tree: systemd → gunicorn master → N workers, each with its own memory and its own database connections — which is why connection count follows process count, not traffic. PIDs are kernel-assigned and reused, so never store one. Signal the master, not the workers: `SIGTERM` drains, `SIGHUP` reloads, and `SIGKILL` (9) "cannot be caught, blocked, or ignored", so it loses every in-flight request. Threads share memory and, under the GIL, buy concurrency while waiting on I/O — not parallel CPU.