use fixed array of ctx to avoid consuming all fds#14
Conversation
| proc cleanUpResources[T](ctx: ptr FFIContext[T]): Result[void, string] = | ||
| ## Full cleanup for heap-allocated contexts: closes all resources and frees memory. | ||
| defer: | ||
| freeShared(ctx) | ||
| return ctx.closeResources() |
There was a problem hiding this comment.
We could have a single cleanup proc and add a freeCtx: bool = false (or default to true, if that makes more sense)
| ctx.onNotResponding() | ||
| return err("failed to signal reqSignal on time in destroyFFIContext") | ||
|
|
||
| let wdSignaled = ctx.watchdogStopSignal.fireSync().valueOr: |
There was a problem hiding this comment.
wdSignaled is the same as above, should have the same name. I'd just called it stop or maybe stopSignaled, but call it that everywhere
9e4943f to
048dc59
Compare
048dc59 to
9469f71
Compare
gmelodie
left a comment
There was a problem hiding this comment.
Besides the other comments, do we even use this at all?
proc destroyFFIContext[T](ctx: ptr FFIContext[T]): Result[void, string] =I see that tests introduced all use pool.destroyFFIContext
| # This call is a no-op unless -d:ffiGenBindings is passed to the compiler. | ||
| genBindings() # reads -d:ffiOutputDir, -d:ffiNimSrcRelPath, -d:targetLang from compile flags | ||
| genBindings() | ||
| # reads -d:ffiOutputDir, -d:ffiNimSrcRelPath, -d:targetLang from compile flags |
There was a problem hiding this comment.
nit: maybe this comment should be inside the definition of genBindings? Here it may cause confusion as to what it refers to
| ) | ||
| ) | ||
|
|
||
| let poolDecl = quote do: |
| for i in 0 ..< MaxFFIContexts: | ||
| var expected = false |
There was a problem hiding this comment.
| for i in 0 ..< MaxFFIContexts: | |
| var expected = false | |
| const expected = false | |
| for i in 0 ..< MaxFFIContexts: |
There was a problem hiding this comment.
Thanks but compareExchange in atomics requires a var:
proc compareExchange[T: not Trivial](location: var Atomic[T]; expected: var T;
desired: T; order: MemoryOrder = moSequentiallyConsistent): bool|
|
||
| joinThread(ctx.ffiThread) | ||
| joinThread(ctx.watchdogThread) | ||
| ctx.cleanUpResources().isOkOr: |
There was a problem hiding this comment.
This line seems to be the only difference between the two destroyFFIContext implementations, maybe we could wrap the rest in another function and make the two impls call the new function? e.g.
proc newFn(ctx...) =
unregisterCtx(cast[pointer](ctx))
...
joinThread(ctx.ffiThread)
joinThread(ctx.watchdogThread)
# then ...
proc destroyFFIContext*[T](
pool: var FFIContextPool[T], ctx: ptr FFIContext[T]
): Result[void, string] =
newFn(ctx)
pool.releaseSlot(ctx)
return ok()
# and ...
proc destroyFFIContext[T](ctx: ptr FFIContext[T]): Result[void, string] =
newFn(ctx)
ctx.cleanUpResources().isOkOr:
return err("cleanUpResources failed: " & $error)
return ok()There was a problem hiding this comment.
I think it was confusing because both had the same name but one call the other.
The b53f3ce may have enhanced that.
NagyZoltanPeter
left a comment
There was a problem hiding this comment.
Yepp, this is needed but I see a bit of discrepancy in between we reserve slots and store the ctx pointer in there while we have another store for ctx ptrs.
I suggest a bit of rework here, eliminate that contextRegistry for which we always do a lock at every api call and just use the slot registry for the same puropse - for validating the ctx ptr - reading slot registry does not need a lock.
Wow! Great catch, thanks @NagyZoltanPeter ! |
CBOR is the headline 0.2.0 feature, not 0.1.4: at v0.1.4 serial.nim was still JSON/string-based, so the prior CBOR attribution was wrong. Also complete the 0.2.0 scope (events, registry, codegen) ahead of tagging. Date 0.1.4 by its last functional change (#14, 2026-05-13) rather than the later changelog/version-bump commits, so the version reflects when its code actually settled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CBOR is the headline 0.2.0 feature, not 0.1.4: at v0.1.4 serial.nim was still JSON/string-based, so the prior CBOR attribution was wrong. Also complete the 0.2.0 scope (events, registry, codegen) ahead of tagging. Date 0.1.4 by its last functional change (#14, 2026-05-13) rather than the later changelog/version-bump commits, so the version reflects when its code actually settled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Use fixed array of 32 context to allow reuse them and hence, prevent app from running out of file descriptors.
Notice that this is mostly needed for testing purposes. For example, we detected an issue when dealing with Go unit tests that started/stopped several contexts, without recycling, and then the test process run out of FDs.
closes #4
p.s.: there are some other minor changes like enhancing the error handling, use of wait signal in watchdog to allow fast shutdown (and make tests faster.)