Skip to content
Kavachकवच

Panics: When a program stops

● Intermediate2 min

How a program ends tells the shell what happened: 0 for success, 1 for an error from main, 101 for a panic in main.

What happenedPrinted to standard errorExit code
It finishednothing0
main returned an errorerror: <message>1
A panic in the main taskpanic: <message>, then at <file>:<line>101
Ctrl+C (SIGINT)nothing130
The terminal or console closed (SIGHUP)nothing129
SIGTERM (how Docker and systemd stop a program; on Windows, logging off or shutting down)nothing143

These messages never go to standard output, so a program's real output stays clean when it is piped into another program.

  • Ctrl+C, a closed terminal and SIGTERM end the program the way cli.exit does: what it printed is flushed, and logs and traces are sent before it ends. A second Ctrl+C ends it at once.
  • This holds for kavach run and for programs built with kavach build.
decision 0062 · crashes and clocks

Finishing before a stop

A program with work it must not cut off (requests being answered, a file half written, a queue to empty) takes a hold with cli.on_stop(grace). While a hold is kept, the first stop signal doesn't end the program: hold.asked() turns true, and the program finishes what it is doing.

use std.cli
use std.time

fn main() uses Clock {
    const hold = cli.on_stop(grace: 30.seconds)
    while not hold.asked() {
        work_a_little()
    }
    save_progress()         // Docker's SIGTERM: this still runs
    hold.done()
}
syntax: Kavach code
  • The program ends, with the signal's exit code, once every hold is let go of with hold.done(), when the longest grace has passed, or when main returns.
  • A second signal ends it at once.
  • A hold needs no capability. http.serve takes one of its own, so a server finishes the requests under way before the program ends.

Without a stop signal, hold.asked() stays false:

use std.cli

fn main() {
    const hold = cli.on_stop(grace: 30.seconds)
    let rounds = 0
    while not hold.asked() and rounds < 3 {
        rounds += 1
    }
    print("asked: {hold.asked()}, rounds: {rounds}")
    print("saving progress")
    hold.done()
}

The program ran and printed:

kavach run on-stop.kav

asked: false, rounds: 3saving progress
on-stop.kav: Kavach code, then what running it prints