use `race` instead of `or` to avoid lockup (#1042)

This commit is contained in:
Etan Kissling 2024-03-04 00:06:32 +01:00 committed by GitHub
parent 0b753e7cf2
commit 9059a8aced
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 14 additions and 4 deletions

View File

@ -266,7 +266,9 @@ method readOnce*(
raise newLPStreamRemoteClosedError()
if channel.recvQueue.len == 0:
channel.receivedData.clear()
await channel.closedRemotely or channel.receivedData.wait()
try: # https://github.com/status-im/nim-chronos/issues/516
discard await race(channel.closedRemotely, channel.receivedData.wait())
except ValueError: raiseAssert("Futures list is not empty")
if channel.closedRemotely.done() and channel.recvQueue.len == 0:
channel.returnedEof = true
channel.isEof = true

View File

@ -55,7 +55,9 @@ proc bridge*(connSrc: Connection, connDst: Connection) {.async.} =
try:
while not connSrc.closed() and not connDst.closed():
await futSrc or futDst
try: # https://github.com/status-im/nim-chronos/issues/516
discard await race(futSrc, futDst)
except ValueError: raiseAssert("Futures list is not empty")
if futSrc.finished():
bufRead = await futSrc
if bufRead > 0:

View File

@ -97,7 +97,10 @@ proc handleConn(s: Secure,
let
fut1 = conn.join()
fut2 = sconn.join()
await fut1 or fut2 # one join() completes, cancel outstanding join()
try: # https://github.com/status-im/nim-chronos/issues/516
discard await race(fut1, fut2)
except ValueError: raiseAssert("Futures list is not empty")
# at least one join() completed, cancel pending one, if any
if not fut1.finished: await fut1.cancelAndWait()
if not fut2.finished: await fut2.cancelAndWait()
block:

View File

@ -68,7 +68,10 @@ proc connHandler*(self: TcpTransport,
let
fut1 = client.join()
fut2 = conn.join()
await fut1 or fut2 # one join() completes, cancel outstanding join()
try: # https://github.com/status-im/nim-chronos/issues/516
discard await race(fut1, fut2)
except ValueError: raiseAssert("Futures list is not empty")
# at least one join() completed, cancel pending one, if any
if not fut1.finished: await fut1.cancelAndWait()
if not fut2.finished: await fut2.cancelAndWait()