mirror of
https://github.com/logos-storage/nim-libplum.git
synced 2026-06-07 09:40:01 +00:00
Fix handle close
This commit is contained in:
parent
baa8d7a819
commit
d65e1098e2
@ -77,8 +77,8 @@ type
|
|||||||
resolvedInternalPort: uint16
|
resolvedInternalPort: uint16
|
||||||
resolvedExternalPort: uint16
|
resolvedExternalPort: uint16
|
||||||
resolvedExternalHost: array[PLUM_MAX_HOST_LEN, char]
|
resolvedExternalHost: array[PLUM_MAX_HOST_LEN, char]
|
||||||
# Use abandoned pattern for memory freeing
|
# Refcount-like
|
||||||
abandoned: Atomic[bool]
|
signalReleases: Atomic[int]
|
||||||
onStateChange: PlumStateCallback
|
onStateChange: PlumStateCallback
|
||||||
|
|
||||||
# libplum calls mappingCallback from its own C thread. Under refc, any thread
|
# libplum calls mappingCallback from its own C thread. Under refc, any thread
|
||||||
@ -97,6 +97,10 @@ var activeMappings {.guard: activeMappingsLock.}: Table[cint, MappingHandle]
|
|||||||
|
|
||||||
initLock(activeMappingsLock)
|
initLock(activeMappingsLock)
|
||||||
|
|
||||||
|
proc releaseSignal(handle: MappingHandle) {.raises: [].} =
|
||||||
|
if handle.signalReleases.fetchAdd(1) == 1:
|
||||||
|
discard handle.signal.close()
|
||||||
|
|
||||||
# We can be confident that the pattern is GC Safe using
|
# We can be confident that the pattern is GC Safe using
|
||||||
# a lock.
|
# a lock.
|
||||||
template withSafeLock(body: untyped) =
|
template withSafeLock(body: untyped) =
|
||||||
@ -118,12 +122,7 @@ proc mappingCallback(
|
|||||||
if plumState == Destroyed:
|
if plumState == Destroyed:
|
||||||
withSafeLock:
|
withSafeLock:
|
||||||
activeMappings.del(id)
|
activeMappings.del(id)
|
||||||
# The handle can be abandoned after a timeout during a
|
handle.releaseSignal()
|
||||||
# mapping creation.
|
|
||||||
# In that case, destroy is called internally and the
|
|
||||||
# signal pointer can be closed.
|
|
||||||
if handle.abandoned.load():
|
|
||||||
discard handle.signal.close()
|
|
||||||
# Release the pin set in createMapping: the C library is done with the
|
# Release the pin set in createMapping: the C library is done with the
|
||||||
# raw pointer and will never call this callback again for this mapping.
|
# raw pointer and will never call this callback again for this mapping.
|
||||||
GC_unref(handle)
|
GC_unref(handle)
|
||||||
@ -230,40 +229,23 @@ proc createMapping*(
|
|||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
if not completed:
|
if not completed:
|
||||||
# Timeout or cancellation: we cannot close the signal here because
|
# Timeout or cancellation: a late callback may still fireSync, so the
|
||||||
# the C callback may fire later and call fireSync on it.
|
# mapping is torn down and the close is decided by releaseSignal.
|
||||||
# Mark the handle as abandoned so the DESTROYED callback closes it.
|
|
||||||
# Access via activeMappings rather than the local `handle` ref,
|
|
||||||
# in order to make sure we have the valid reference.
|
|
||||||
withSafeLock:
|
|
||||||
let h = activeMappings.getOrDefault(id)
|
|
||||||
if not h.isNil:
|
|
||||||
h.abandoned.store(true)
|
|
||||||
discard plum_destroy_mapping(id)
|
discard plum_destroy_mapping(id)
|
||||||
else:
|
handle.releaseSignal()
|
||||||
# Signal fired normally, safe to close.
|
|
||||||
discard signal.close()
|
|
||||||
|
|
||||||
# Reached only when completed = true (CancelledError skips this).
|
# Reached only when completed = true (CancelledError skips this).
|
||||||
if not completed:
|
if not completed:
|
||||||
return err("plum: mapping " & $id & " timed out")
|
return err("plum: mapping " & $id & " timed out")
|
||||||
|
|
||||||
# Read result via activeMappings rather than the local `handle` ref in
|
let resolvedState = handle.resolvedState
|
||||||
# order to make sure we have the valid reference.
|
let resolvedMapping = PlumMapping(
|
||||||
var resolvedState: PlumState
|
protocol: handle.resolvedProtocol,
|
||||||
var resolvedMapping: PlumMapping
|
mappingProtocol: handle.resolvedMappingProtocol,
|
||||||
|
internalPort: handle.resolvedInternalPort,
|
||||||
withSafeLock:
|
externalPort: handle.resolvedExternalPort,
|
||||||
let h = activeMappings.getOrDefault(id)
|
externalHost: $cast[cstring](unsafeAddr handle.resolvedExternalHost),
|
||||||
if not h.isNil:
|
)
|
||||||
resolvedState = h.resolvedState
|
|
||||||
resolvedMapping = PlumMapping(
|
|
||||||
protocol: h.resolvedProtocol,
|
|
||||||
mappingProtocol: h.resolvedMappingProtocol,
|
|
||||||
internalPort: h.resolvedInternalPort,
|
|
||||||
externalPort: h.resolvedExternalPort,
|
|
||||||
externalHost: $cast[cstring](unsafeAddr h.resolvedExternalHost),
|
|
||||||
)
|
|
||||||
|
|
||||||
if resolvedState == Success:
|
if resolvedState == Success:
|
||||||
return ok(MappingResult(id: id, mapping: resolvedMapping))
|
return ok(MappingResult(id: id, mapping: resolvedMapping))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user