From 9059a8aced87741de98813bfe0ef2ed63e0217ab Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Mon, 4 Mar 2024 00:06:32 +0100 Subject: [PATCH] use `race` instead of `or` to avoid lockup (#1042) --- libp2p/muxers/yamux/yamux.nim | 4 +++- libp2p/protocols/connectivity/relay/utils.nim | 4 +++- libp2p/protocols/secure/secure.nim | 5 ++++- libp2p/transports/tcptransport.nim | 5 ++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/libp2p/muxers/yamux/yamux.nim b/libp2p/muxers/yamux/yamux.nim index 92f1ade898..fc50c07d5d 100644 --- a/libp2p/muxers/yamux/yamux.nim +++ b/libp2p/muxers/yamux/yamux.nim @@ -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 diff --git a/libp2p/protocols/connectivity/relay/utils.nim b/libp2p/protocols/connectivity/relay/utils.nim index 60fedb7f1c..ac1965921c 100644 --- a/libp2p/protocols/connectivity/relay/utils.nim +++ b/libp2p/protocols/connectivity/relay/utils.nim @@ -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: diff --git a/libp2p/protocols/secure/secure.nim b/libp2p/protocols/secure/secure.nim index 0f820b002b..6b1cc7b665 100644 --- a/libp2p/protocols/secure/secure.nim +++ b/libp2p/protocols/secure/secure.nim @@ -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: diff --git a/libp2p/transports/tcptransport.nim b/libp2p/transports/tcptransport.nim index 531c8e517d..0241ec8da4 100644 --- a/libp2p/transports/tcptransport.nim +++ b/libp2p/transports/tcptransport.nim @@ -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()