mirror of
https://github.com/logos-messaging/nim-ffi.git
synced 2026-06-21 16:59:30 +00:00
destroyFFIContext stopped and joined the worker threads on every release, and createFFIContext rebuilt them on the next acquire. Each cycle therefore allocated a fresh worker — 4 ThreadSignalPtr socketpairs + the ffi/watchdog thread chronos dispatcher kqueues — and never reclaimed the old ones (the pool deliberately skips closing them, relying on slot reuse that never actually reused the resources). A consumer that creates and destroys contexts repeatedly (e.g. nim-sds ReliabilityManager) leaked ~10 fds per cycle, unbounded. Make the pool genuinely reuse a slot's worker: - Track per-slot `initialized`; createFFIContext builds the worker once and reuses it on every later acquisition of the same slot. - Add releaseFFIContext: parks a context (returns its slot) WITHOUT stopping the threads, so the next acquire reuses the same fds. It also drops the stale C event callback so a watchdog tick on a parked slot cannot invoke a callback whose user-data the consumer may already have freed. The caller is responsible for quiescing its library object (on the FFI thread) first. - destroyFFIContext keeps full-teardown semantics for error/non-pooling paths and now marks the slot uninitialised so a later acquire rebuilds it. Tests: add a park & reuse suite (same-slot live-worker reuse, callback/lib pointer dropped on park, and fd usage bounded across 20 park/reuse cycles). The fd test fails by ~10 fds/cycle against the pre-fix behaviour. Green under both --mm:refc and --mm:orc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>