xtc_supervisor(3)
---xtc_supervisor(3)
OTP-style supervisor trees
| XTC_SUPERVISOR(3) | Library Functions Manual | XTC_SUPERVISOR(3) |
NAME
xtc_sup_start,
xtc_sup_add_child,
xtc_sup_stop, xtc_sup_join,
xtc_sup_alive,
xtc_sup_n_children,
xtc_sup_n_alive,
xtc_sup_n_restarts —
OTP-style supervisor trees
SYNOPSIS
#include <xtc.h>
#include <xtc_orc.h>
int
xtc_sup_start(xtc_loop_t
*loop, const
xtc_sup_opts_t *opts,
const xtc_child_spec_t
*children, int
n_children,
xtc_supervisor_t
**out_sup);
int
xtc_sup_add_child(xtc_supervisor_t
*sup, const
xtc_child_spec_t *spec,
xtc_pid_t *out_pid);
int
xtc_sup_stop(xtc_supervisor_t
*sup);
int
xtc_sup_join(xtc_supervisor_t
*sup, int64_t
timeout_ns);
int
xtc_sup_alive(const
xtc_supervisor_t *sup);
int
xtc_sup_n_children(const
xtc_supervisor_t *sup);
int
xtc_sup_n_alive(const
xtc_supervisor_t *sup);
int
xtc_sup_n_restarts(const
xtc_supervisor_t *sup);
DESCRIPTION
xtc_supervisor is an OTP-style supervisor:
it owns a set of child specs, spawns them, observes failures, and restarts
them per the configured strategy. Failures isolate to children; the
supervisor's own liveness is independent of any single child.
Strategies control which children get restarted on a child crash:
XTC_SUP_ONE_FOR_ONE- Only the crashed child restarts.
XTC_SUP_ONE_FOR_ALL- All children restart.
XTC_SUP_REST_FOR_ONE- The crashed child and all started after it (right siblings) restart, in order.
XTC_SUP_SIMPLE_ONE_FOR_ONE- Children spawned dynamically; not all known up front.
Group
restarts never overlap. Under
XTC_SUP_ONE_FOR_ALL and
XTC_SUP_REST_FOR_ONE the supervisor asks every
affected child to exit and then WAITS until each one's cleanup has completed
-- until it has left the process table, which happens only after all of its
xtc_proc_at_exit(3) hooks have returned -- before it
starts any replacement. A replacement therefore never runs beside a
predecessor that still holds a shared resource.
The wait is bounded, at 5 seconds. If an old
child has not finished cleaning up by then, the supervisor does NOT start a
replacement beside it; it stops instead, which its caller observes through
xtc_sup_join().
Releases before 1.50 killed the siblings, marked them dead and respawned at once, so a replacement could run while its predecessor was still inside an exit hook.
Restart policies per child:
XTC_RESTART_PERMANENT- Always restart on exit (normal or crash).
XTC_RESTART_TRANSIENT- Restart on abnormal exit only.
XTC_RESTART_TEMPORARY- Never restart; one-shot.
Restart intensity: opts.max_restarts restarts within opts.period_ns exhausts the supervisor; it gives up and exits. Default: 1 in 5 seconds.
Bounded
dynamic pool: for the XTC_SUP_SIMPLE_OFO
strategy, set opts.max_children >
0 to cap the number of live dynamic children;
xtc_sup_add_child()
returns XTC_E_RESOURCE once the cap is reached (a
slot freed by a child's DOWN is reusable).
opts.max_children == 0 is
unbounded.
xtc_sup_n_children()
returns the number of children the supervisor manages: every static child
(from xtc_sup_start(), alive or not) plus every
dynamic child that is alive or being restarted. A dynamic child that exits
for good (XTC_RESTART_TEMPORARY,
or XTC_RESTART_TRANSIENT
with a normal exit) is removed from the supervisor
and no longer counted (before 1.55.1 its slot was kept forever);
xtc_sup_n_alive()
returns only the currently-live children (pool utilization).
xtc_sup_start()
spawns the supervisor and its initial children. Returns
XTC_OK with *out_sup set, or
XTC_E_INVAL on bad args (notably
n_children
<= 0);
empty supervisors not supported, see
examples/06_sqlxtc/main.c for a one-listener-child
workaround .
xtc_sup_add_child()
adds one child to a running supervisor from a
xtc_child_spec_t, returning the new child's pid in
*out_pid. This is the dynamic path used with a
simple_one_for_one
supervisor, whose children are spawned on demand rather than all listed up
front.
xtc_sup_stop()
asynchronously requests shutdown. Children get ‘EXIT’ signals;
the supervisor exits when all are done.
xtc_sup_join() waits up to
timeout_ns for the supervisor to exit, then frees it
(-1 waits forever, 0 polls once). It returns XTC_OK
once the supervisor has exited and been freed; the pointer is then invalid.
If the supervisor is still running when the wait ends it returns
XTC_E_AGAIN and frees nothing: the pointer stays
valid, so the caller can xtc_sup_stop() it and join
again. Call it from outside the supervisor's loop thread. Releases before
1.50 ignored the wait's result and freed the supervisor anyway, so a join
that timed out returned XTC_OK and freed memory the
still-running supervisor was using.
SEE ALSO
HISTORY
Appeared in xtc 0.1.
| May 28, 2026 | Debian |