How does runserver restart even after a SyntaxError?

We’ve all run the runserver management command in development. Django of course prints something like:

Loading .env environment variables...
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
January 31, 2024 - 14:25:18
Django version 5.0.1, using settings 'project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Of course, this command uses the django.utils.autoreload module to watch for file changes and reload the development server to reflect the changes.

However, there’s one useful feature of runserver that isn’t explained by autoreload alone. If a SyntaxError is introduced somewhere in the code, a traceback will be printed to the console as expected, however the runserver command will not end. Fixing the SyntaxError and saving the file will still trigger a reload:

...
SyntaxError: expected ':'
/home/username/project/app/views.py changed, reloading.
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
January 31, 2024 - 14:34:04
Django version 5.0.1, using settings 'project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

What I don’t understand is how to replicate this behaviour in my own management commands. I can copy the runserver source code directly into my own custom management command called foo.py, and this behaviour will not carry over. foo will watch for file changes and restart just fine, but if a SyntaxError is introduced, it crashes altogether and spits me back into the shell.

Is there anyone with a better knowledge of the runserver command who can to shine a light on this?