avoid finalizer, may destabilize the GC (#28)

forgot about https://github.com/nim-lang/Nim/issues/4851 when writing it

generally, will only be a problem if threads are created and destroyed
often
This commit is contained in:
Jacek Sieka 2020-12-16 15:00:21 +01:00 committed by GitHub
parent a9d5cba699
commit af9611c187
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 17 additions and 10 deletions

View File

@ -88,7 +88,7 @@ type
## Representation of recoverable signature. ## Representation of recoverable signature.
data: secp256k1_ecdsa_recoverable_signature data: secp256k1_ecdsa_recoverable_signature
SkContext* = ref object SkContext = object
## Representation of Secp256k1 context object. ## Representation of Secp256k1 context object.
context: ptr secp256k1_context context: ptr secp256k1_context
@ -132,14 +132,21 @@ template ptr0(v: array|openArray): ptr cuchar =
template ptr0(v: SkMessage): ptr cuchar = template ptr0(v: SkMessage): ptr cuchar =
ptr0(distinctBase(v)) ptr0(distinctBase(v))
func shutdownLibsecp256k1(ctx: SkContext) = proc releaseThread*(T: type SkContext): T =
# TODO: use destructor when finalizer are deprecated for destructors if not isNil(secpContext.context):
if not(isNil(ctx.context)): secp256k1_context_destroy(secpContext.context)
secp256k1_context_destroy(ctx.context) secpContext.context = nil
proc newSkContext(): SkContext = proc init(T: type SkContext): T =
## Create new Secp256k1 context object. ## Create new Secp256k1 context object - when no longer needed, it should be
new(result, shutdownLibsecp256k1) ## destroyed
# TODO We _should_ release the context on thread shutdown but there's no
# reliable way to do that short of doing it manually, which the code is
# not really prepared for - unfortunately, nim finalizers are broken:
# https://github.com/nim-lang/Nim/issues/4851
# A workaround is to call SkContext.releaseThread() on thread end - this
# will become a no-op when the issue is fixed
let flags = cuint(SECP256K1_CONTEXT_VERIFY or SECP256K1_CONTEXT_SIGN) let flags = cuint(SECP256K1_CONTEXT_VERIFY or SECP256K1_CONTEXT_SIGN)
result.context = secp256k1_context_create(flags) result.context = secp256k1_context_create(flags)
secp256k1_context_set_illegal_callback( secp256k1_context_set_illegal_callback(
@ -156,8 +163,8 @@ func getContext(): ptr secp256k1_context =
# Technically, it should be possible to precompute a static context # Technically, it should be possible to precompute a static context
# at compile time and use that instead, which would turn this into # at compile time and use that instead, which would turn this into
# a truly side-effect-free function, instead of an as-if-free one. # a truly side-effect-free function, instead of an as-if-free one.
if isNil(secpContext): if isNil(secpContext.context):
secpContext = newSkContext() secpContext = SkContext.init()
secpContext.context secpContext.context
func fromHex*(T: type seq[byte], s: string): SkResult[T] = func fromHex*(T: type seq[byte], s: string): SkResult[T] =