The recycle/async-destroy work changed the Nim `ffiDtor` export from
`int destroy(ctx)` to `int destroy(ctx, callback, userData)`, but the C++
and Rust generators still emitted the 1-arg signature. Foreign callers
therefore passed only `ctx`; inside Nim, `callback`/`userData` held
uninitialised register garbage. `requestRecycle` stored the garbage
callback and the recycle handler later invoked it — a jump through a wild
pointer that segfaulted in every C++ E2E / ASan / TSan job (the crash
surfaced at teardown, after each test's assertions had already passed).
Generate the 3-arg ABI and have the destructor/Drop block on the recycle
callback via the existing sync-call helper, so the pool slot is fully
drained and parked before the handle goes away — otherwise rapid
create/destroy churn (StressShortLivedPerThreadContext, ThreadedHammer)
could outrun the recycle and exhaust the pool.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Call initializeLibrary() (setupForeignThreadGc) in the `.ffi.` request
wrapper and in add/remove_event_listener so a foreign (Go) caller thread
has an initialised Nim heap before any allocation ($reqTypeName /
$eventName / registry ops). Without it such a thread segfaults in the
allocator under GC pressure — the production unwrap SIGSEGV.
- recycleContext resets the event registry/queue + stuck flag on park so a
reused pool slot starts clean.
- ffiDtor doc/cleanup for the async recycle ABI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* rust examples: sync main.rs + tokio main.rs demoing the listener API
Adds two bundled examples to the generated Rust crate:
- examples/main.rs: sync flow using std::sync::mpsc to bridge a typed
on_echo_fired listener into main + a wildcard add_event_listener
that uses decode_event_payload::<EchoEvent>(envelope) for the
matching event id.
- examples/tokio_main.rs: same shape via #[tokio::main] +
tokio::sync::mpsc.
Bumps generateCargoToml to ship `[dev-dependencies]` with tokio's
`rt-multi-thread` + `macros` features so the bundled examples can use
#[tokio::main] without polluting the library's runtime profile.
Run with `cargo run --example main` (set DYLD_LIBRARY_PATH=<repo> on
macOS until build.rs emits an rpath).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* simplify examples
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>