Fix `or` deadlock issue. (#517)
* Fix `or` should not create future with OwnCancelSchedule flag set. * Fix `CancelledError` missing from raises list when both futures has empty raises list. * Fix macros tests.
This commit is contained in:
parent
5dfa3fd7fa
commit
1eb834a2f9
|
@ -786,7 +786,7 @@ template orImpl*[T, Y](fut1: Future[T], fut2: Future[Y]): untyped =
|
|||
fut2.addCallback(cb)
|
||||
|
||||
retFuture.cancelCallback = cancellation
|
||||
return retFuture
|
||||
retFuture
|
||||
|
||||
proc `or`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
||||
## Returns a future which will complete once either ``fut1`` or ``fut2``
|
||||
|
@ -801,7 +801,7 @@ proc `or`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
|||
## completed, the result future will also be completed.
|
||||
##
|
||||
## If cancelled, ``fut1`` and ``fut2`` futures WILL NOT BE cancelled.
|
||||
var retFuture = newFuture[void]("chronos.or")
|
||||
var retFuture = newFuture[void]("chronos.or()")
|
||||
orImpl(fut1, fut2)
|
||||
|
||||
|
||||
|
@ -1665,10 +1665,9 @@ proc `or`*[T, Y, E1, E2](
|
|||
fut1: InternalRaisesFuture[T, E1],
|
||||
fut2: InternalRaisesFuture[Y, E2]): auto =
|
||||
type
|
||||
InternalRaisesFutureRaises = union(E1, E2)
|
||||
InternalRaisesFutureRaises = union(E1, E2).union((CancelledError,))
|
||||
|
||||
let
|
||||
retFuture = newFuture[void]("chronos.wait()", {FutureFlag.OwnCancelSchedule})
|
||||
let retFuture = newFuture[void]("chronos.or()", {})
|
||||
orImpl(fut1, fut2)
|
||||
|
||||
proc wait*(fut: InternalRaisesFuture, timeout = InfiniteDuration): auto =
|
||||
|
|
|
@ -135,6 +135,16 @@ suite "Asynchronous issues test suite":
|
|||
await server.closeWait()
|
||||
return true
|
||||
|
||||
proc testOrDeadlock(): Future[bool] {.async.} =
|
||||
proc f(): Future[void] {.async.} =
|
||||
await sleepAsync(2.seconds) or sleepAsync(1.seconds)
|
||||
let fx = f()
|
||||
try:
|
||||
await fx.cancelAndWait().wait(2.seconds)
|
||||
except AsyncTimeoutError:
|
||||
return false
|
||||
true
|
||||
|
||||
test "Issue #6":
|
||||
check waitFor(issue6()) == true
|
||||
|
||||
|
@ -152,3 +162,6 @@ suite "Asynchronous issues test suite":
|
|||
|
||||
test "IndexError crash test":
|
||||
check waitFor(testIndexError()) == true
|
||||
|
||||
test "`or` deadlock [#516] test":
|
||||
check waitFor(testOrDeadlock()) == true
|
||||
|
|
|
@ -491,7 +491,7 @@ suite "Exceptions tracking":
|
|||
proc testit2 {.async: (raises: [IOError]).} =
|
||||
raise (ref IOError)()
|
||||
|
||||
proc test {.async: (raises: [ValueError, IOError]).} =
|
||||
proc test {.async: (raises: [CancelledError, ValueError, IOError]).} =
|
||||
await testit() or testit2()
|
||||
|
||||
proc noraises() {.raises: [].} =
|
||||
|
|
Loading…
Reference in New Issue