Skip to content

66-supervise

The per-service process supervisor. 66-supervise keeps a single service running according to its declared policy: it runs the service's run script, restarts it when it dies (within a crash budget), runs its finish script on the way down, tracks readiness, and records the service's status. It is the native supervisor of 66 (historically inspired by s6-supervise) and is launched — one instance per service — by 66-scandir.

Interface

66-supervise servicename

66-supervise is not meant to be run directly. 66-scandir spawns it for every service it finds, with its current working directory set to the scandir and servicename as its only argument. The supervisor then changes into the service directory, reads the service's resolve database (./.resolve) and supervises it.

To act on a supervised service, use the friendly, resolve-aware commands 66 start, 66 stop and 66 signal; the low-level, resolve-independent control primitive is 66-svctl.

Behaviour

One 66-supervise process supervises exactly one service:

  • It runs the service's run script and waits for it. When the process dies it is restarted, unless a down request is in effect (see Files).
  • For a service that declares a readiness notification descriptor, the supervisor waits for the service to announce it is ready before reporting it up and ready. It gives the service its [Start] Timeout to do so, counted from the start of its process, whatever brings it up. When the time runs out, the supervisor brings it down by the way down below, the service stays down and supervised, its result reads timeout-start and the timeout-start event is sent; it is not started again until the next start. Without a readiness notification descriptor, a service is up as soon as its process starts, and nothing is timed.
  • When the service is brought down, the supervisor sends it the configured down signal, then runs the service's finish script before going back to a down state. The way down, the finish script included, waits for the [Stop] Timeout of the service, never for its [Start] Timeout; once it has passed, the supervisor sends SIGKILL and the result reads timeout-stop. A [Stop] Timeout the frontend does not write is the general stop delay chosen at the build of 66, 10000 milliseconds unless the -D default-stop-timeout= option of meson setup says otherwise; 0 written means without end, and no SIGKILL is sent. A logger gets the general stop delay.
  • A service wanted up again while it is on its way down is not killed: it is brought back up.
  • An order that does not change the state of the service, such as bringing up a service that runs, sends no event.
  • At every transition it writes the service's status to supervise/status so that 66 status and the rest of 66 can report it.

Configuration

Unlike a classic supervisor that reads a set of per-service files, 66-supervise takes its configuration directly from the service's resolve database, compiled by 66 parse from the frontend file. The relevant frontend keys are:

  • Notify (in [Start]): the file descriptor on which the service announces its readiness.
  • Timeout (in [Start]): the time a service with Notify has to become ready.
  • Timeout (in [Stop]): the time the way down may take before SIGKILL, as written by the parse, the general stop delay when the frontend does not write it.
  • MaxDeath / MaxDeathInterval (in [Start]): the crash budget (see Crash budget).
  • DownSignal (in [Stop]): the signal sent to the service to bring it down.

The only configuration kept as a runtime file is down: its presence means keep the service down. 66 start and 66 stop create and remove it.

Files

66-supervise manages the following entries in the service's live directory:

  • supervise/status: a fixed-size binary status record (state, result, provenance, pid, timestamps and crash counter). It is read by 66 status.
  • supervise/control: the control fifo on which the supervisor receives its commands.
  • supervise/lock: guarantees that a single 66-supervise process supervises a given service.
  • down: the runtime down request described above.

Crash budget

If a service dies MaxDeath times (or more) within MaxDeathInterval milliseconds, 66-supervise stops restarting it and marks it as failed (crash limit reached). A successful 66 start resets the budget. Setting MaxDeath = 0 disables the budget entirely (infinite restart).

A service whose run script cannot be executed at all (for example a non-executable file) is reported as an exec failure with a progressive, bounded backoff; this is kept separate from the crash budget and never counts towards it.

Control

66-supervise listens on supervise/control for single-byte commands — bring up, bring down, restart, reload, send a signal, exit, and so on. You normally never write to this fifo yourself: 66 start, 66 stop, 66 signal and the 66-svctl primitive do it for you.