Panic and Signals
Beyond normal shutdown, Zolo offers two hooks for exceptional situations:
on panic for uncaught fatal errors, and on signal for signals sent by the
operating system.
Panic hook
on panic e receives the error message as a string and runs immediately when
panic(...) is called without a surrounding try/catch. After the on panic
block, the runtime still fires any registered on shutdown hooks — useful for
writing failure logs before exiting:
on panic captures the message from panic("boom") before on shutdown
shuts down the process. Run locally — the WASM sandbox does not safely execute
intentional panics.
// Verifies `on panic` fires before `on shutdown` on uncaught panic.
on panic e {
print("panic hook saw: {e}")
}
on shutdown reason {
print("shutdown reason: {reason}")
}
print("about to crash")
panic("boom")
Requires the Zolo CLI/host — open in the playground or run locally.
Signal hook
on signal SIGINT { ... } registers a handler for a specific OS signal. The
block runs asynchronously when the signal is delivered to the process.
process.raise("SIGINT") synthesizes the signal in-process — on Windows only
SIGINT and SIGTERM are supported:
process.raise("SIGINT") delivers the signal; the hook increments fired and
prints the count. process.sleep(50) gives the signal thread time to enqueue
the event before the next interruption point. Run locally to observe the full
sequence.
// Verifies `on signal` is invoked when a signal is delivered to the process.
// `process.raise` synthesises a signal in-process; on Windows only SIGINT
// (Ctrl+C) and SIGTERM (Ctrl+Break) can be raised this way.
use std::process
var fired = 0
on signal SIGINT {
fired = fired + 1
print("signal hook fired ({fired})")
}
on shutdown reason {
print("shutdown reason: {reason}")
}
print("raising SIGINT...")
process.raise("SIGINT")
// Give the signal thread a beat to enqueue the event before we hit the
// next interrupt check point.
process.sleep(50)
print("after sleep — fired={fired}")
print("done")
Requires the Zolo CLI/host — open in the playground or run locally.
Challenge
Add a second on signal SIGINT and verify that both fire when
process.raise("SIGINT") is called. Then switch to SIGTERM and confirm that
the first block does not interfere.