yggdrasil.environ.shutdown¶
shutdown ¶
yggdrasil.environ.shutdown
Shutdown callback registry for process exit and termination signals.
Callbacks are run on: - normal interpreter exit via atexit - termination-related signals such as SIGINT / SIGTERM / SIGHUP / SIGBREAK when available on the current platform and installable from the current thread
Design notes¶
- Signal handlers do NOT raise synthetic SystemExit into arbitrary stack frames. Instead they run callbacks, restore the previous handler, and re-raise the signal to the process so the OS / previous handler decides what happens next. This avoids injecting exceptions into finally blocks and C extensions.
- run() is both run-once and re-entrancy safe: a signal arriving while atexit callbacks are executing will NOT start a parallel run, and will NOT truncate the in-flight run.
- Bound methods are tracked via weakref.WeakMethod so registering an instance method does not extend the instance's lifetime, and does not suffer from id() reuse after GC.
- atexit is registered eagerly at module import so ordering relative to other libraries is predictable (LIFO at import time).
Typical usage¶
from yggdrasil.environ import shutdown as yg_shutdown
yg_shutdown.register(cleanup)
yg_shutdown.unregister(cleanup)
ShutdownRegistry ¶
ShutdownRegistry(
*,
handled_signals: Iterable[int] | None = None,
raise_on_callback_error: bool = False
)
Registry for cleanup callbacks triggered by atexit and termination signals.
install ¶
Install the atexit hook and signal handlers.
Safe to call multiple times. If called outside the main thread, atexit is still registered but signal handlers are skipped.
uninstall ¶
Restore previous signal handlers.
atexit registration is intentionally left in place; run() is idempotent so leaving the runner registered is harmless.
register ¶
register(
callback: Callback | None = None,
*,
priority: int = 0,
pass_reason: bool = False,
install: bool = True
)
Register a callback.
If pass_reason=True, the callback will receive one positional argument: reason: str
Bound methods are held via weakref so the registry does not extend the instance's lifetime.
callbacks ¶
Return currently live callbacks in execution order.
Dead weak references are skipped (but not pruned here; pruning happens in run() or via the WeakMethod finalizer).
run ¶
Run registered callbacks once.
Re-entrancy safe: if a signal arrives while this is already running, the nested call is a no-op and does NOT truncate the in-flight run.
Subsequent top-level calls are also no-ops until reset_run_state() is called.
register ¶
Convenience alias for the shared registry register().
unregister ¶
Convenience alias for the shared registry unregister().