diff --git a/chronos/asyncproc.nim b/chronos/asyncproc.nim index f0087767..572e3828 100644 --- a/chronos/asyncproc.nim +++ b/chronos/asyncproc.nim @@ -1010,12 +1010,14 @@ else: retFuture.fail(newException(AsyncProcessError, osErrorMsg(res.error()))) + timer = nil + proc cancellation(udata: pointer) {.gcsafe.} = - if not(retFuture.finished()): - if not(isNil(timer)): - clearTimer(timer) - # Ignore any errors because of cancellation. - discard removeProcess2(processHandle) + if not(isNil(timer)): + clearTimer(timer) + timer = nil + # Ignore any errors because of cancellation. + discard removeProcess2(processHandle) if timeout != InfiniteDuration: timer = setTimer(Moment.fromNow(timeout), continuation, cast[pointer](2)) diff --git a/chronos/internal/asyncfutures.nim b/chronos/internal/asyncfutures.nim index 1a2be757..d479f674 100644 --- a/chronos/internal/asyncfutures.nim +++ b/chronos/internal/asyncfutures.nim @@ -1338,13 +1338,15 @@ proc sleepAsync*(duration: Duration): Future[void] {. proc completion(data: pointer) {.gcsafe.} = if not(retFuture.finished()): retFuture.complete() + timer = nil # Release circular reference (for gc:arc) proc cancellation(udata: pointer) {.gcsafe.} = - if not(retFuture.finished()): + if not isNil(timer): clearTimer(timer) + timer = nil # Release circular reference (for gc:arc) retFuture.cancelCallback = cancellation - timer = setTimer(moment, completion, cast[pointer](retFuture)) + timer = setTimer(moment, completion) return retFuture proc sleepAsync*(ms: int): Future[void] {. @@ -1437,6 +1439,7 @@ proc withTimeout*[T](fut: Future[T], timeout: Duration): Future[bool] {. if not(isNil(timer)): clearTimer(timer) fut.completeFuture() + timer = nil # TODO: raises annotation shouldn't be needed, but likely similar issue as # https://github.com/nim-lang/Nim/issues/17369 @@ -1447,6 +1450,7 @@ proc withTimeout*[T](fut: Future[T], timeout: Duration): Future[bool] {. fut.cancelSoon() else: fut.completeFuture() + timer = nil if fut.finished(): retFuture.complete(true) @@ -1499,6 +1503,7 @@ proc waitImpl[F: SomeFuture](fut: F, retFuture: auto, timeout: Duration): auto = if not(isNil(timer)): clearTimer(timer) fut.completeFuture() + timer = nil var cancellation: proc(udata: pointer) {.gcsafe, raises: [].} cancellation = proc(udata: pointer) {.gcsafe, raises: [].} = @@ -1509,6 +1514,8 @@ proc waitImpl[F: SomeFuture](fut: F, retFuture: auto, timeout: Duration): auto = else: fut.completeFuture() + timer = nil + if fut.finished(): fut.completeFuture() else: