Skip to content

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.

03-on-panic.zolo
// 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.

04-on-signal.zolo
// 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.

enespt-br