A tiny init process written in Zig for Linux containers, designed for signal forwarding, orphan process collection, and safer PID 1 shutdown behavior.
- Signal Forwarding: Forward signals from parent process to child processes
- Orphan Process Collection: Acts as a child subreaper to collect orphaned processes
- Parent Death Signal: Configurable signal when parent process dies
- Signal Rewriting: Remap incoming signals before forwarding them
- Exit Code Mapping: Translate known child exit codes to success when needed
- Terminal Control: Properly handles terminal process groups for interactive applications
- Debug Support: Optional tracing mode for debugging child processes
- Zig compiler (>= 0.16.0-dev.2860)
- Linux >= 3.4 (for PR_SET_CHILD_SUBREAPER)
- Linux kernel with signalfd support
git clone <repo_url> && cd zinit
zig build -Doptimize=ReleaseSafeThe binary will be installed to zig-out/bin/zinit.
Usage: zinit [OPTIONS] -- <command> [args...]
Options:
-h, --help Show help and exit
-v, --version Show version and exit
--log-level <LEVEL> Set log level: error, warning, info, or debug
-p, --signal <SIGNAL> Signal to send when parent process dies
-s, --subreaper Enable child subreaper mode explicitly
-r, --rewrite <OLD:NEW> Rewrite a signal before forwarding (can be repeated)
-e, --expect-exit <CODE> Treat child exit code as success (0)
--forward-mode <MODE> Signal forwarding mode: Child (default) or ProcessGroup
Signal formats:
- Number: 15, 9, 2
- Name: TERM, KILL, INT (with or without SIG prefix)
- Realtime: RTMIN, RTMIN+1, RTMAX, RTMAX-1
When zinit runs as PID 1, it automatically enables child subreaper mode to properly reap orphaned descendant processes. This is the recommended usage:
# Dockerfile
COPY zinit /sbin/zinit
ENTRYPOINT ["/sbin/zinit", "--", "/bin/sh", "-c", "exec my-app"]When running zinit outside of PID 1 (e.g., as a supervisor process), explicitly enable subreaper mode:
zinit --subreaper -- /usr/bin/my-daemonFor applications that spawn worker processes, use ProcessGroup mode to ensure all processes receive signals:
zinit --forward-mode ProcessGroup -- /bin/sh -c "stress-ng --cpu 4"Some applications exit with specific codes that should be treated as success:
# Java applications often exit with 143 (128 + SIGTERM)
zinit -e 143 -- java -jar app.jarSome applications expect different signals than what the container runtime sends:
# Convert SIGTERM to SIGINT for graceful shutdown
zinit -r TERM:INT -- /bin/sh -c "trap 'exit 0' INT; sleep infinity"Ensure the child process receives a signal when zinit itself dies unexpectedly:
zinit -p KILL -- /usr/bin/critical-service#!/sbin/zinit -- /bin/sh
export APP_ENV=production
exec /usr/bin/my-applicationzinit --forward-mode ProcessGroup -- /bin/sh -c '
nginx &
php-fpm &
wait
'# Build with tracing support
zig build -Dtracing-child=true -Doptimize=ReleaseSafe
# Run with strace
ZINIT_TRACING_CHILD=ON strace -f -p $(pgrep zinit)
# Send SIGUSR1 to let child continue
kill -USR1 <child_pid>| Variable | Values | Description |
|---|---|---|
ZINIT_TRACING_CHILD |
ON, OFF |
Override build-time tracing configuration |
| Option | Description |
|---|---|
-Dtracing-child=true |
Child waits for SIGUSR1 before exec (for debugging) |
-Doptimize=ReleaseSafe |
Build with safety checks and optimizations |
-Doptimize=ReleaseFast |
Build with maximum optimizations |
-Doptimize=ReleaseSmall |
Build for minimal binary size |
- Signal Setup: Blocks all signals and creates a signalfd for synchronous signal handling
- Subreaper Mode: Enables child subreaper (automatic when PID 1, or with
--subreaper) - Fork: Creates child process with new session and process group
- Terminal Setup: Sets up controlling terminal for interactive applications
- Event Loop: Polls signalfd and timerfd for events
- Signal Forwarding: Forwards signals to child (with optional rewriting)
- Graceful Shutdown: On child exit, sends SIGTERM to descendants, then SIGKILL after 5 seconds
# Debug build
zig build
# Run tests
zig build test
# Run with coverage
zig build test -Dtest-coverage=true
# Run application
zig build run -- /bin/bashMIT License. See LICENSE for details.