xtc_xproc(3)

---

xtc_xproc(3)

cross-fork spawn, send, and monitor

XTC_XPROC(3) Library Functions Manual XTC_XPROC(3)

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_maybecross-fork spawn, send, and monitor

library “libxtc”

#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);

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.

() 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 () there, and portably.

() 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. () 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.

() sends a byte payload (copied) to the child's root proc; it arrives in that proc's mailbox as an ordinary () message.

() 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 ()). 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.

() returns the child's OS pid (for logging), or -1. () signals and reaps the child if still running, closes the channel, and frees the handle; it is idempotent.

() is the child-side entry that xtc_xspawn() arranges automatically; it is public so a re-exec'd child can re-enter its runtime.

() is wired as the first statement of () 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).

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.

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.

xtc_osproc(3), xtc_proc(3), xtc_net(3), xtc(7)

July 10, 2026 Debian

View the mdoc source