protect against mem leag in case of failures sending requests to ffi thread

This commit is contained in:
Ivan FB 2026-04-24 12:48:01 +02:00
parent bb8a3e7e22
commit c6cbb08de3
No known key found for this signature in database
GPG Key ID: DF0C67A04C543270
3 changed files with 16 additions and 1 deletions

View File

@ -60,18 +60,23 @@ proc sendRequestToFFIThread*(
## Sending the request
let sentOk = ctx.reqChannel.trySend(ffiRequest)
if not sentOk:
deleteRequest(ffiRequest)
return err("Couldn't send a request to the ffi thread")
let fireSyncRes = ctx.reqSignal.fireSync()
if fireSyncRes.isErr():
deleteRequest(ffiRequest)
return err("failed fireSync: " & $fireSyncRes.error)
if fireSyncRes.get() == false:
deleteRequest(ffiRequest)
return err("Couldn't fireSync in time")
## wait until the FFI working thread properly received the request
let res = ctx.reqReceivedSignal.waitSync(timeout)
if res.isErr():
## Do not free ffiRequest here: the FFI thread was already signaled and
## will process (and free) it.
return err("Couldn't receive reqReceivedSignal signal")
## Notice that in case of "ok", the deallocShared(req) is performed by the FFI Thread in the

View File

@ -6,11 +6,16 @@ import std/[json, macros], results, tables
import chronos, chronos/threadsync
import ./ffi_types, ./internal/ffi_macro, ./alloc
type FFIDestroyContentProc* = proc(content: pointer) {.nimcall.}
type FFIThreadRequest* = object
callback: FFICallBack
userData: pointer
reqId*: cstring
reqContent*: pointer
deleteReqContent*: FFIDestroyContentProc
## Called by sendRequestToFFIThread on failure to free reqContent when
## the FFI thread will never process (and thus never free) this request.
proc init*(
T: typedesc[FFIThreadRequest],
@ -26,7 +31,9 @@ proc init*(
ret[].reqContent = reqContent
return ret
proc deleteRequest(request: ptr FFIThreadRequest) =
proc deleteRequest*(request: ptr FFIThreadRequest) =
if not request[].deleteReqContent.isNil():
request[].deleteReqContent(request[].reqContent)
deallocShared(request[].reqId)
deallocShared(request)

View File

@ -164,6 +164,9 @@ proc buildFfiNewReqProc(reqTypeName, body: NimNode): NimNode =
let typeStr = $T
var ret =
FFIThreadRequest.init(callback, userData, typeStr.cstring, `reqObjIdent`)
proc destroyContent(content: pointer) {.nimcall.} =
ffiDeleteReq(cast[ptr `reqTypeName`](content))
ret[].deleteReqContent = destroyContent
return ret
)