PR #71 stood up the event thread + bounded queue but left dispatch
inline, so a blocking consumer callback stalled request processing on
the FFI thread. Wire the producer side onto the existing queue: the FFI
thread now enqueues (copyToShared/dupSharedCString/enqueueFFIEvent) and
returns immediately; the event thread drains and invokes callbacks under
reg.lock. This keeps the event thread as watchdog *and* dispatcher.
Because callbacks no longer run on the FFI thread, a callback may issue a
synchronous sendRequestToFFIThread without tripping the reentrancy guard
(the FFI thread is separate) — a callback still must not add/remove
listeners on its own registry. A wedged callback fills the queue and
latches eventQueueStuck, which sendRequestToFFIThread surfaces as backpressure.
Reworked the lock-during-invocation test to drive through the real event
thread, and added a test for the now-safe sync-request-from-callback path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* protect against mem leak in case of failures sending requests to ffi thread
* better cleanup if failures in createFFIContext
* avoid dangling cstring in handleRes under ARC/ORC
* better resource cleanup in destroyFFIContext
* invoke onNotResponding if failure in destroyFFIContext
* correct seq copy in alloc
* make sure the lock is init before cleanUpResources
* better possible exception handling in processReq
* guard allocSharedSeq if given seq is empty
* enhance error handling in ffi_context
* add new tests and some corrections