The process lifecycle
A process is born when its parent asks the OS to create it, lives through the running/ready/waiting states from lesson 3-1, and dies when it finishes or crashes. At death, it leaves one last message for its parent: the exit code, a small integer.
The convention is universal:
- 0 means success. (Zero errors.)
- Anything else means failure, and the specific number can say why.
Every tool you will ever use in a career respects this: shell scripts, git, test runners, and CI pipelines — CI stands for continuous integration, a server that automatically runs your project's tests and checks on every change a developer pushes. When a CI pipeline marks a build red, it is literally reading an exit code.
In Python you can create a child process with the subprocess module and inspect its exit code.
Code exercise · python
Run this. It launches a child Python process, captures what the child printed, and reads its exit code. sys.executable is the path to the Python that is currently running.
Code exercise · python
Run this. The child crashes (dividing by zero), and the parent sees a non-zero exit code without crashing itself.
Choosing your own exit code
A program can pick its exit code with sys.exit(n). Well-behaved command-line tools use this to report what kind of failure happened, so scripts can react.
In the shell, $? holds the exit code of the last command, and && runs the next command only if the previous one exited 0:
python3 deploy_checks.py && python3 deploy.py
If the checks exit non-zero, the deploy never runs. That one convention, success is 0, powers most automation on Earth.
Code exercise · python
Your turn. Run two children: one exits with code 0, one with code 2. For each, print "NAME -> ok" if the code is 0, otherwise "NAME -> failed with code N". The loop and the children are set up for you, fill in the if/else.
Quiz
A CI pipeline runs your test suite and the process exits with code 1. What does the pipeline do and why?