Skip to content
Process Management Contract

Process Management Contract

Before you add programs to Super, read this page. It defines the contract between Super and the workloads it supervises. Violations may lead to orphaned processes, untracked PIDs, or zombies that Super cannot clean up.

1. Foreground only

Every application managed by Super must run in foreground / non-daemonized mode.

This rule applies to child programs ([[programs]]), not to how you start superd itself. superd may run in the foreground (default, required under systemd/Docker) or optionally self-daemonize with superd --daemon / [server] daemon = true when you are not using an init system — see Installation — Systemd.

Managed programs must not:

  • Call fork() and exit the parent while leaving a detached child running.
  • Call setsid() or otherwise detach from the controlling terminal to “daemonize” themselves.

Super tracks the process it spawns. If your app exits the parent immediately after forking, Super believes the service has stopped while work continues outside its control.

Examples

ApplicationDo thisNot this
Nginxnginx -g "daemon off;"Default daemon mode
Node.jsnode app.jsCustom double-fork wrapper
Custom servicesRun the main process in the foregroundShell script that forks and exits

Configure command / args in super.toml so the main PID Super starts is the real service, not a launcher that exits after forking.

2. No double-fork or PGID escape

Any attempt to double-fork, escape the process group (PGID), or otherwise run outside the tree Super created is considered a contract violation.

Super assigns a process group before spawn and stops services with kill(-PGID, …) so the direct tree is torn down together. Processes that break out of that group are orphans: Super does not guarantee tracking, signal delivery, or forced cleanup for them.

If you need a traditional system daemon, run it under the host init (systemd) — not under Super.

3. Zombies and init separation

Super follows separation of concerns with the host OS:

LayerRole
Host init (systemd on bare metal, Tini / dumb-init as PID 1 in containers)Reap adopted zombies, handle PID 1 duties
SuperOrchestrate managed services, health checks, dependencies, graceful shutdown of its process trees

Super is not a global zombie reaper. A global SIGCHLD handler would compete with Tokio’s child.wait() on managed processes and can cause deadlocks or race conditions.

If a managed app spawns short-lived children and does not wait() on them, those zombies are the responsibility of:

  1. The application (prefer exec over shell wrappers, or call wait()), or
  2. The host/container init wrapper.

For Docker and Kubernetes, see Container Deployment.

Summary

RuleRequirement
ForegroundNo self-daemonization (fork + exit parent, setsid, etc.)
Process groupStay inside the PGID Super created; no escape
ZombiesHost init reaps; Super orchestrates, does not replace PID 1

Super enforces this contract by design. Workloads that need full init-system semantics belong at the machine or container level, not inside a supervised application slot.