Skip to content

Commit e01b5f5

Browse files
committed
chore: destroyFFIContext refuse static context
1 parent 5c0ce69 commit e01b5f5

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

ffi/ffi_context_pool.nim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,18 @@ proc createFFIContext*[T](
4141
return err("createFFIContext: initContextResources failed: " & $error)
4242
ok(ctx)
4343

44+
proc isStaticCtx[T](pool: var FFIContextPool[T], ctx: ptr FFIContext[T]): bool =
45+
## `staticCtx` is published before the state flips, so `Ready` implies it is readable.
46+
pool.staticState.load() == StaticCtxReady and
47+
pool.staticCtx.load() == cast[pointer](ctx)
48+
4449
proc destroyFFIContext*[T](
4550
pool: var FFIContextPool[T], ctx: ptr FFIContext[T]
4651
): Result[void, string] =
4752
## On thread-exit timeout the slot is leaked; closing live-thread resources is unsafe.
53+
# Destroying it would release the slot while `staticState` still points at it.
54+
if pool.isStaticCtx(ctx):
55+
return err("destroyFFIContext(pool): the {.ffiStatic.} context outlives every ctx")
4856
ctx.stopAndJoinThreads().isOkOr:
4957
return err("destroyFFIContext(pool): " & $error)
5058
# Required: next acquisition would otherwise re-init a live lock (UB).

tests/unit/test_ffi_context.nim

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,18 @@ suite "FFIContextPool":
163163
for c in ctxs:
164164
discard sharedPool.destroyFFIContext(c)
165165

166+
test "destroyFFIContext refuses the static context but not a plain one":
167+
let staticCtx = sharedPool.staticFFIContext().valueOr:
168+
assert false, "staticFFIContext failed: " & $error
169+
return
170+
check sharedPool.destroyFFIContext(staticCtx).isErr()
171+
# Still live and still the same context, not a released slot.
172+
check sharedPool.staticFFIContext().tryGet() == staticCtx
173+
let plain = sharedPool.createFFIContext().valueOr:
174+
assert false, "createFFIContext(pool) failed: " & $error
175+
return
176+
check sharedPool.destroyFFIContext(plain).isOk()
177+
166178
test "a failed create leaves staticFFIContext retryable":
167179
var ctxs: array[MaxFFIContexts, ptr FFIContext[TestLib]]
168180
for i in 0 ..< MaxFFIContexts:

0 commit comments

Comments
 (0)