Skip to content

v0.0.59, when the interpreter stops

Choose a tag to compare

@tamnd tamnd released this 06 Sep 12:33
· 1 commit to main since this release
v0.0.59
aa03a5c

R08, when the interpreter stops, in #189.

The last lesson about the runtime as a thing with a lifetime. R01 asked what has already happened before your first line, and this one asks what is still to come after your last one. Every cell starts a child interpreter, because a notebook cannot watch its own shutdown.

The cells walk the order of the end with sys.is_finalizing() next to each step, show atexit callbacks coming back newest first and one registered during shutdown that never runs, ask a late __del__ what it can still reach and find its module globals intact but sys.modules empty, let a callback and a finalizer both raise while the exit status stays at zero, catch the single generation two collection, and leave a subinterpreter open so its warning turns up.

The case worth the lesson is the daemon thread. Pass time.sleep and your finalizers run. Pass a function defined in your own module and its stack frame holds your module's globals, so the module dict is never cleared and nothing in it is freed. The debug recording puts a number on it: 12680 references still alive at the end, against zero for the same objects held any other way.

Two Tier 1 recordings on a release build and a debug build, twelve citations, six diagrams, and three glossary terms. Also a stale count fixed in R07, which said seven sample extensions where the table has eight.

M8 now has R09 left to write.