xtc_inject(3)

---

xtc_inject(3)

fault-injection points

XTC_INJECT(3) Library Functions Manual XTC_INJECT(3)

xtc_inject_attach, xtc_inject_attach_wait, xtc_inject_detach, xtc_inject_trigger, xtc_inject_check, xtc_inject_wakeup, xtc_inject_n_attached, XTC_INJECTION_POINTfault-injection points

#include <xtc.h>
#include <xtc_inject.h>

int
xtc_inject_attach(const char *name, xtc_inject_fn fn, void *user);

int
xtc_inject_attach_wait(const char *name);

int
xtc_inject_detach(const char *name);

void
xtc_inject_trigger(const char *name);

int
xtc_inject_check(const char *name);

int
xtc_inject_wakeup(const char *name);

int
xtc_inject_n_attached(void);

xtc_inject is a fault-injection framework modeled on PostgreSQL's src/include/utils/injection_point.h. Production code sprinkles (name) calls at interesting locations (error paths, race windows, slow paths). Tests can attach a callback or ‘wait’ semantics to a named point at runtime; when the point fires, the callback runs (or the trigger blocks until () is called from the test).

() returns the number of injection-point names that currently have attachments -- a diagnostic for tests to confirm setup or teardown.

:

Bind a callback (or "wait" semantics) to the name. Up to 4 attachments per name.
Remove all attachments for a name.
Fire the point. No-op if nothing attached (production fast path).

() is a lock-free probe: returns 1 if the name has any attachments, 0 otherwise. Production code uses this to substitute an error path:

if (xtc_inject_check("io.calloc_fail")) {
    xtc_inject_trigger("io.calloc_fail");
    return XTC_E_NOMEM;
}

The hot-path cost when nothing is attached is one atomic load (the global ‘attached_count’).

: defining XTC_INJECT_DISABLE elides all () calls to a no-op. Production builds may opt out entirely; debug and test builds keep the framework live.

/* In production code: */
int xtc_io_init(xtc_io_t **out) {
    XTC_INJECTION_POINT("io.init.calloc_fail");
    if (xtc_inject_check("io.init.calloc_fail"))
        return XTC_E_NOMEM;
    /* ... real code ... */
}

/* In a test: */
xtc_inject_attach("io.init.calloc_fail", my_callback, NULL);
int rc = xtc_io_init(&io);
munit_assert_int(rc, ==, XTC_E_NOMEM);
xtc_inject_detach("io.init.calloc_fail");

xtc_log(3), xtc(7)

Appeared in xtc 0.1.

May 28, 2026 Debian

View the mdoc source