xtc_xproc(3)
---xtc_xproc(3)
cross-fork spawn, send, and monitor
| XTC_XPROC(3) | Library Functions Manual | XTC_XPROC(3) |
NAME
xtc_xspawn,
xtc_xproc_register_entry,
xtc_xspawn_entry,
xtc_xproc_destroy,
xtc_xproc_os_pid, xtc_xsend,
xtc_xmonitor, xtc_xlink,
xtc_xproc_child_main,
xtc_xproc_win_child_maybe —
cross-fork spawn, send, and monitor
LIBRARY
library “libxtc”
SYNOPSIS
#include
<xtc_xproc.h>
int
xtc_xspawn(xtc_loop_t
*loop, const char
*name, xtc_xproc_root_fn
root_fn, const void
*arg, size_t
arg_len, xtc_xproc_t
**out);
int
xtc_xproc_register_entry(const
char *name,
xtc_xproc_root_fn
fn);
int
xtc_xspawn_entry(xtc_loop_t
*loop, const char
*name, const char
*entry, const void
*arg, size_t
arg_len, xtc_xproc_t
**out);
void
xtc_xproc_destroy(xtc_xproc_t
*p);
long
xtc_xproc_os_pid(const
xtc_xproc_t *p);
int
xtc_xsend(xtc_xproc_t
*p, const void
*msg, size_t
len);
int
xtc_xmonitor(xtc_xproc_t
*p, uint64_t
*out_ref);
int
xtc_xlink(xtc_xproc_t
*p);
int
xtc_xproc_child_main(int
ctrl_fd,
xtc_xproc_root_fn
root_fn, void
*arg);
int
xtc_xproc_win_child_maybe(int
argc, char
**argv);
DESCRIPTION
These extend the Erlang-style process relations across a fork(2) boundary: a parent spawns a child that runs its OWN xtc runtime, and can send to it and monitor it as if it were a local process. This is the single-host subset of the (unbuilt) distributed design -- a stepping stone toward cluster support, built over a local socketpair rather than TCP.
xtc_xspawn()
forks a child running root_fn, which receives a
private copy of the arg /
arg_len bytes the parent passed. The parent gets an
xtc_xproc_t handle in *out. It
must be called from a fiber on loop (the monitor relay
lives there). On a platform without fork(2) it returns
XTC_E_NOSYS, because a raw function pointer does not
survive process creation there (a Windows child is a fresh image, not a
clone of the parent) -- use
xtc_xspawn_entry()
there, and portably.
xtc_xproc_register_entry()
registers a child root function under a NAME in a process-global table. The
same binary -- parent and any re-exec'd child -- resolves the name to the
same function, which is the portable bridge for platforms where a function
pointer cannot cross process creation. Call it once, early, in code that
runs in BOTH the parent and the child image.
xtc_xspawn_entry()
spawns a child running the function registered under
entry: on fork(2) platforms it forks
and resolves the name in the child; on Windows it re-execs this binary,
which resolves the name in its own copy of the registry. It is otherwise
identical to xtc_xspawn() (monitor, send, destroy
all behave the same) and returns XTC_E_NOTFOUND if
entry is not registered. This is the portable and
Windows-capable spawn form.
xtc_xsend()
sends a byte payload (copied) to the child's root proc; it arrives in that
proc's mailbox as an ordinary
xtc_recv()
message.
xtc_xmonitor()
monitors the child from the calling fiber. When the child exits, crashes, or
its control channel dies, the caller receives a normal xtc DOWN message
(decode with
xtc_down_decode_ex()).
The DOWN's reason carries the child's exit code, or
the signal number if the child was killed by a signal, or
XTC_DOWN_KIND_NOCONNECTION if the channel died
before a clean exit was seen. Internally the child's fate is mirrored into a
local shadow proc, so all the ordinary monitor/DOWN machinery applies
unchanged.
xtc_xlink()
is the bidirectional form (like xtc_link(3) across the
fork boundary): the child's exit delivers an EXIT signal to the linking
fiber, and if the linking fiber / parent process dies the child observes its
control channel close and shuts down. It links to the same shadow proc
xtc_xmonitor() uses, so the intra-process link
machinery extends across the fork unchanged.
xtc_xproc_os_pid()
returns the child's OS pid (for logging), or -1.
xtc_xproc_destroy()
signals and reaps the child if still running, closes the channel, and frees
the handle; it is idempotent.
xtc_xproc_child_main()
is the child-side entry that xtc_xspawn() arranges
automatically; it is public so a re-exec'd child can re-enter its
runtime.
xtc_xproc_win_child_maybe()
is wired as the first statement of
main()
in a binary that hosts xtc_xspawn_entry() children.
On Windows, if the cross-process-child sentinel argv is present it connects
the control channel, receives its arg, runs the registered entry, and exits
without returning; otherwise it is a no-op and normal startup continues. On
fork(2) platforms it is always a no-op (the child is
fork'd, not re-exec'd).
RETURN VALUES
xtc_xspawn(),
xtc_xsend(), and
xtc_xmonitor() return XTC_OK
or a negative XTC_E_* code (notably
XTC_E_NOSYS where fork(2) is
unavailable). xtc_xproc_os_pid() returns the OS pid
or -1. xtc_xproc_child_main() returns the child's
exit code.
xtc_xproc_destroy() returns no value.
NOTES
POSIX only; the Windows build declines every entry point with
XTC_E_NOSYS.
Because cross-fork spawn uses a real fork(2) and waitpid(2), it is deliberately NOT reachable by the deterministic simulator (the sim is single-process and cannot observe a real child's schedule) -- the same boundary that keeps native AIO and the thread pool out of the sim. It is covered by the unit test tier (test/m10/test_xproc.c); a future DST model would run both sides as loops over a simulated socketpair, as the distributed design describes.
SEE ALSO
| July 10, 2026 | Debian |