1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
|
.\"
.\" Copyright (c) 2025-2026, Leafscale, LLC. All rights reserved.
.\" Use is subject to license terms.
.\"
.Dd March 6, 2026
.Dt ZYGINIT 8
.Os Hammerhead
.Sh NAME
.Nm zyginit
.Nd init daemon and service supervisor for Zygaena/Hammerhead
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
.Nm
is the init daemon (PID 1) and service supervisor for the
Zygaena/Hammerhead operating system.
It replaces SMF
.Pq Service Management Facility
with a single-process, TOML-configured service manager.
.Pp
At boot,
.Nm
performs the following sequence:
.Bl -enum
.It
Scans the enabled services directory for symlinks
.Pq see Sx CONFIGURATION .
.It
Reads each service's TOML definition to extract dependencies.
.It
Performs a topological sort to determine parallel boot tiers.
.It
Starts services tier by tier, respecting dependency order.
.It
Opens a Unix domain socket for
.Xr zygctl 8
communication.
.It
Enters the main event loop, monitoring process contracts, signals,
and the control socket via
.Xr poll 2 .
.El
.Pp
.Nm
supervises all managed services.
When a service exits, the restart policy defined in its TOML definition
determines whether the service is restarted, placed into maintenance,
or left stopped.
.Ss Service Types
.Nm
supports three service types:
.Bl -tag -width "transient"
.It Sy daemon
A long-running process.
.Nm
monitors the process via a Hammerhead process contract and applies the
restart policy when it exits.
.It Sy oneshot
A short-lived process that runs once at boot
.Pq e.g., mounting filesystems, configuring network interfaces .
Once it exits successfully, the service is considered
.Dq done .
A non-zero exit places the service into the
.Sy failed
state.
.It Sy transient
A process started on demand via
.Xr zygctl 8
that is not started automatically at boot.
.El
.Ss Service States
Each managed service is in one of the following states:
.Bl -tag -width "maintenance"
.It Sy disabled
The service is not enabled for boot
.Pq no symlink in Ar enabled.d .
.It Sy waiting
The service is waiting to start
.Pq dependency not yet met or restart delay pending .
.It Sy starting
The service is being started
.Pq fork/exec in progress .
.It Sy running
The service process is alive and being monitored.
.It Sy stopping
A stop has been requested; waiting for the process to exit.
.It Sy stopped
The service has exited and will not be restarted.
.It Sy failed
The service exited abnormally
.Pq oneshot with non-zero exit, or unrecoverable error .
.It Sy maintenance
The service has exceeded its maximum restart count.
Administrative intervention is required.
Use
.Xr zygctl 8
to clear and restart.
.El
.Ss Process Contracts
On Hammerhead,
.Nm
uses kernel process contracts
.Pq see Xr contract 5
to track all descendants of a service process.
This ensures that orphaned grandchild processes are properly managed
and that
.Nm
receives notification when all processes in a service's contract have exited.
.Pp
When
.Nm
is restarted
.Pq e.g., for an upgrade ,
it re-adopts existing contracts so that running services are not disrupted.
.Pp
On systems without process contract support,
.Nm
falls back to direct PID-based monitoring via
.Xr waitpid 2 .
.Ss Signal Handling
.Nm
handles the following signals:
.Bl -tag -width "SIGCHLD"
.It Dv SIGTERM , Dv SIGINT
Initiate graceful shutdown.
All running services are stopped in reverse boot order.
.It Dv SIGHUP
Reload service configuration.
The daemon re-scans
.Pa /etc/zyginit/enabled.d/
and compares with the current service table.
Newly-enabled services are started; disabled services are stopped.
This is equivalent to the
.Cm reload
command in
.Xr zygctl 8 .
.It Dv SIGCHLD
Reap exited child processes and dispatch to the service supervisor.
.It Dv SIGPIPE
Ignored.
.El
.Sh CONFIGURATION
.Nm
reads its service definitions from
.Pa /etc/zyginit/ .
Each service is defined by a TOML file in that directory.
See
.Xr zyginit 5
for the full service definition format.
.Ss Enabling and Disabling Services
Services are enabled by creating a symlink in the
.Pa enabled.d
subdirectory:
.Bd -literal -offset indent
/etc/zyginit/enabled.d/sshd -> ../sshd.toml
.Ed
.Pp
To enable a service:
.Bd -literal -offset indent
# zygctl enable sshd
.Ed
.Pp
To disable:
.Bd -literal -offset indent
# zygctl disable sshd
.Ed
.Pp
These operations can also be performed manually with
.Xr ln 1
and
.Xr rm 1 .
.Sh ENVIRONMENT
.Bl -tag -width "ZYGINIT_CONFIG_DIR"
.It Ev ZYGINIT_CONFIG_DIR
Path to the service definition directory.
Default:
.Pa /etc/zyginit
.It Ev ZYGINIT_SOCKET
Path to the Unix domain socket for
.Xr zygctl 8
communication.
Default:
.Pa /var/run/zyginit.sock
.It Ev ZYGINIT_LOG_DIR
Path to the per-service log directory.
Service stdout and stderr are captured here.
Default:
.Pa /var/run/zyginit/log
.El
.Sh FILES
.Bl -tag -width "/etc/zyginit/enabled.d/"
.It Pa /sbin/init
The init daemon binary
.Pq kernel exec target on Hammerhead .
.It Pa /etc/zyginit/
Directory containing service definition TOML files.
.It Pa /etc/zyginit/enabled.d/
Symlinks to enabled service definitions.
Only services with a symlink here are started at boot.
.It Pa /var/run/zyginit.sock
Unix domain socket for administrative communication.
Created after tmpfs is mounted.
.It Pa /var/run/zyginit/log/
Per-service output log directory.
Each service's stdout and stderr are captured to
.Pa <name>.log
in this directory.
Log files are truncated on each service start.
.El
.Sh LIVE REPLACE
.Nm
supports operator-driven, in-place replacement of the PID-1 process
via
.Xr execve 2
without disturbing running services.
The operator drops a new binary at
.Pa /sbin/init
and runs
.Xr zygctl 8
.Cm replace .
The running
.Nm
serializes its in-memory service-supervision state to
.Pa /var/run/zyginit/state.toml
\(em
service name, contract ID, restart count, uptime
\(em
unlinks the control socket, then
.Xr execve 2 Ns 's
.Pa /sbin/init .
PID-1 in-place
.Xr execve 2
preserves
.Va proc_t.p_ct_process ,
so the kernel-level contract ownership survives the swap; the new
.Nm
process re-reads
.Pa /var/run/zyginit/state.toml ,
re-establishes its userspace bookkeeping, and continues supervising.
.Pp
The boot-id sentinel
.Pq Pa /proc/1/stat
field 22 on Linux;
.Pa /proc/1/psinfo
.Va pr_start.tv_sec
on Hammerhead
is read at startup by the new
.Nm
to detect stale state files left over from before a real reboot.
PID 1's process start time survives
.Xr execve 2
.Pq same proc_t
but changes on real reboot
.Pq new PID 1 .
A mismatch causes the new
.Nm
to ignore (and delete) the file and proceed as a fresh boot.
.Pp
This mechanism is for live upgrades only; it does not cover crash
recovery, since
.Nm
crashing as PID 1 is already a system-level event.
See
.Xr zygctl 8
.Cm replace
for invocation details.
.Sh EXAMPLES
Start
.Nm
in non-init mode for testing
.Pq not as PID 1 :
.Bd -literal -offset indent
# ZYGINIT_CONFIG_DIR=/etc/zyginit zyginit
.Ed
.Sh SEE ALSO
.Xr zygctl 8 ,
.Xr zyginit 5 ,
.Xr contract 5
.Sh HISTORY
.Nm
first appeared in Zygaena/Hammerhead as a replacement for SMF
.Pq Service Management Facility .
.Sh AUTHORS
.An Chris Tusa Aq Mt chris.tusa@leafscale.com
|