diff --git a/ffi/ffi_context.nim b/ffi/ffi_context.nim index f110425..d4d905f 100644 --- a/ffi/ffi_context.nim +++ b/ffi/ffi_context.nim @@ -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 diff --git a/ffi/ffi_thread_request.nim b/ffi/ffi_thread_request.nim index 4f3c119..9ecdd27 100644 --- a/ffi/ffi_thread_request.nim +++ b/ffi/ffi_thread_request.nim @@ -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) diff --git a/ffi/internal/ffi_macro.nim b/ffi/internal/ffi_macro.nim index 0aa7a86..e6a186a 100644 --- a/ffi/internal/ffi_macro.nim +++ b/ffi/internal/ffi_macro.nim @@ -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 )