Skip to content

Multiple Hooks

You can register as many on blocks as you like — of the same type or different types. The runtime organizes them into separate stacks per type and fires them following two rules:

  • on shutdown — LIFO: the last declared block runs first.
  • on panic — fires before on shutdown when the shutdown is caused by an uncaught panic.

The example below registers three on shutdown hooks and one on panic, then runs the program normally (no panic). The three shutdown blocks run in reverse declaration order — 3, 2, 1:

Three on shutdown hooks (LIFO) and one on panic — fired on normal exit. Run locally to see [hook 3], [hook 2], and [hook 1] in that order, plus process.uptime() at the start.

02-multiple-hooks.zolo
// Lifecycle hooks demo — `on shutdown`, `on signal`, `on panic`.

// Companion: specs/lifecycle-hooks.md


use std::process

// Multiple shutdown blocks compose in LIFO order.

on shutdown {
  print("[hook 1] outermost cleanup")
}

on shutdown reason {
  print("[hook 2] reason was: {reason}")
}

on shutdown {
  print("[hook 3] innermost cleanup")
}

on panic e {
  print("[panic] uncaught: {e}")
}

print("uptime at start: {process.uptime()}s")
print("running main work...")

// Trigger normal-exit path; "on shutdown" should fire with reason="normal".

print("done")

Requires the Zolo CLI/host — open in the playground or run locally.

The LIFO order mirrors the defer convention: last in, first out — resources opened most recently are closed before older ones.

enespt-br