fix circular reference in timer (#510)
This commit is contained in:
parent
03d82475d9
commit
c5a5ece487
|
@ -1010,12 +1010,14 @@ else:
|
||||||
retFuture.fail(newException(AsyncProcessError,
|
retFuture.fail(newException(AsyncProcessError,
|
||||||
osErrorMsg(res.error())))
|
osErrorMsg(res.error())))
|
||||||
|
|
||||||
|
timer = nil
|
||||||
|
|
||||||
proc cancellation(udata: pointer) {.gcsafe.} =
|
proc cancellation(udata: pointer) {.gcsafe.} =
|
||||||
if not(retFuture.finished()):
|
if not(isNil(timer)):
|
||||||
if not(isNil(timer)):
|
clearTimer(timer)
|
||||||
clearTimer(timer)
|
timer = nil
|
||||||
# Ignore any errors because of cancellation.
|
# Ignore any errors because of cancellation.
|
||||||
discard removeProcess2(processHandle)
|
discard removeProcess2(processHandle)
|
||||||
|
|
||||||
if timeout != InfiniteDuration:
|
if timeout != InfiniteDuration:
|
||||||
timer = setTimer(Moment.fromNow(timeout), continuation, cast[pointer](2))
|
timer = setTimer(Moment.fromNow(timeout), continuation, cast[pointer](2))
|
||||||
|
|
|
@ -1386,13 +1386,15 @@ proc sleepAsync*(duration: Duration): Future[void] {.
|
||||||
proc completion(data: pointer) {.gcsafe.} =
|
proc completion(data: pointer) {.gcsafe.} =
|
||||||
if not(retFuture.finished()):
|
if not(retFuture.finished()):
|
||||||
retFuture.complete()
|
retFuture.complete()
|
||||||
|
timer = nil # Release circular reference (for gc:arc)
|
||||||
|
|
||||||
proc cancellation(udata: pointer) {.gcsafe.} =
|
proc cancellation(udata: pointer) {.gcsafe.} =
|
||||||
if not(retFuture.finished()):
|
if not isNil(timer):
|
||||||
clearTimer(timer)
|
clearTimer(timer)
|
||||||
|
timer = nil # Release circular reference (for gc:arc)
|
||||||
|
|
||||||
retFuture.cancelCallback = cancellation
|
retFuture.cancelCallback = cancellation
|
||||||
timer = setTimer(moment, completion, cast[pointer](retFuture))
|
timer = setTimer(moment, completion)
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc sleepAsync*(ms: int): Future[void] {.
|
proc sleepAsync*(ms: int): Future[void] {.
|
||||||
|
@ -1487,6 +1489,7 @@ proc withTimeout*[T](fut: Future[T], timeout: Duration): Future[bool] {.
|
||||||
if not(isNil(timer)):
|
if not(isNil(timer)):
|
||||||
clearTimer(timer)
|
clearTimer(timer)
|
||||||
fut.completeFuture()
|
fut.completeFuture()
|
||||||
|
timer = nil
|
||||||
|
|
||||||
# TODO: raises annotation shouldn't be needed, but likely similar issue as
|
# TODO: raises annotation shouldn't be needed, but likely similar issue as
|
||||||
# https://github.com/nim-lang/Nim/issues/17369
|
# https://github.com/nim-lang/Nim/issues/17369
|
||||||
|
@ -1497,6 +1500,7 @@ proc withTimeout*[T](fut: Future[T], timeout: Duration): Future[bool] {.
|
||||||
fut.cancelSoon()
|
fut.cancelSoon()
|
||||||
else:
|
else:
|
||||||
fut.completeFuture()
|
fut.completeFuture()
|
||||||
|
timer = nil
|
||||||
|
|
||||||
if fut.finished():
|
if fut.finished():
|
||||||
retFuture.complete(true)
|
retFuture.complete(true)
|
||||||
|
@ -1549,6 +1553,7 @@ proc waitImpl[F: SomeFuture](fut: F, retFuture: auto, timeout: Duration): auto =
|
||||||
if not(isNil(timer)):
|
if not(isNil(timer)):
|
||||||
clearTimer(timer)
|
clearTimer(timer)
|
||||||
fut.completeFuture()
|
fut.completeFuture()
|
||||||
|
timer = nil
|
||||||
|
|
||||||
var cancellation: proc(udata: pointer) {.gcsafe, raises: [].}
|
var cancellation: proc(udata: pointer) {.gcsafe, raises: [].}
|
||||||
cancellation = proc(udata: pointer) {.gcsafe, raises: [].} =
|
cancellation = proc(udata: pointer) {.gcsafe, raises: [].} =
|
||||||
|
@ -1559,6 +1564,8 @@ proc waitImpl[F: SomeFuture](fut: F, retFuture: auto, timeout: Duration): auto =
|
||||||
else:
|
else:
|
||||||
fut.completeFuture()
|
fut.completeFuture()
|
||||||
|
|
||||||
|
timer = nil
|
||||||
|
|
||||||
if fut.finished():
|
if fut.finished():
|
||||||
fut.completeFuture()
|
fut.completeFuture()
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue