mirror of
https://github.com/logos-storage/nim-chronos.git
synced 2026-01-08 00:13:08 +00:00
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)
|
fut2.addCallback(cb)
|
||||||
|
|
||||||
retFuture.cancelCallback = cancellation
|
retFuture.cancelCallback = cancellation
|
||||||
return retFuture
|
retFuture
|
||||||
|
|
||||||
proc `or`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
proc `or`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
||||||
## Returns a future which will complete once either ``fut1`` or ``fut2``
|
## 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.
|
## completed, the result future will also be completed.
|
||||||
##
|
##
|
||||||
## If cancelled, ``fut1`` and ``fut2`` futures WILL NOT BE cancelled.
|
## 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)
|
orImpl(fut1, fut2)
|
||||||
|
|
||||||
|
|
||||||
@ -1665,10 +1665,9 @@ proc `or`*[T, Y, E1, E2](
|
|||||||
fut1: InternalRaisesFuture[T, E1],
|
fut1: InternalRaisesFuture[T, E1],
|
||||||
fut2: InternalRaisesFuture[Y, E2]): auto =
|
fut2: InternalRaisesFuture[Y, E2]): auto =
|
||||||
type
|
type
|
||||||
InternalRaisesFutureRaises = union(E1, E2)
|
InternalRaisesFutureRaises = union(E1, E2).union((CancelledError,))
|
||||||
|
|
||||||
let
|
let retFuture = newFuture[void]("chronos.or()", {})
|
||||||
retFuture = newFuture[void]("chronos.wait()", {FutureFlag.OwnCancelSchedule})
|
|
||||||
orImpl(fut1, fut2)
|
orImpl(fut1, fut2)
|
||||||
|
|
||||||
proc wait*(fut: InternalRaisesFuture, timeout = InfiniteDuration): auto =
|
proc wait*(fut: InternalRaisesFuture, timeout = InfiniteDuration): auto =
|
||||||
|
|||||||
@ -135,6 +135,16 @@ suite "Asynchronous issues test suite":
|
|||||||
await server.closeWait()
|
await server.closeWait()
|
||||||
return true
|
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":
|
test "Issue #6":
|
||||||
check waitFor(issue6()) == true
|
check waitFor(issue6()) == true
|
||||||
|
|
||||||
@ -152,3 +162,6 @@ suite "Asynchronous issues test suite":
|
|||||||
|
|
||||||
test "IndexError crash test":
|
test "IndexError crash test":
|
||||||
check waitFor(testIndexError()) == true
|
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]).} =
|
proc testit2 {.async: (raises: [IOError]).} =
|
||||||
raise (ref IOError)()
|
raise (ref IOError)()
|
||||||
|
|
||||||
proc test {.async: (raises: [ValueError, IOError]).} =
|
proc test {.async: (raises: [CancelledError, ValueError, IOError]).} =
|
||||||
await testit() or testit2()
|
await testit() or testit2()
|
||||||
|
|
||||||
proc noraises() {.raises: [].} =
|
proc noraises() {.raises: [].} =
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user