better `upgraded` lifetime handling (avoid NPE) (#506)

* avoid npe on connection upgrade

* add `onUpgraded` event
This commit is contained in:
Dmitriy Ryajov 2021-01-18 16:27:29 -06:00 committed by GitHub
parent 64b822e8f0
commit 34e330353f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 12 deletions

View File

@ -240,9 +240,7 @@ proc cleanupConn(c: ConnManager, conn: Connection) {.async.} =
proc onConnUpgraded(c: ConnManager, conn: Connection) {.async.} =
try:
trace "Triggering connect events", conn
doAssert(not isNil(conn.upgraded),
"The `upgraded` event hasn't been properly initialized!")
conn.upgraded.complete()
conn.upgrade()
let peerId = conn.peerInfo.peerId
await c.triggerPeerEvents(

View File

@ -36,6 +36,21 @@ type
proc timeoutMonitor(s: Connection) {.async, gcsafe.}
proc isUpgraded*(s: Connection): bool =
if not isNil(s.upgraded):
return s.upgraded.finished
proc upgrade*(s: Connection, failed: ref Exception = nil) =
if not isNil(failed):
s.upgraded.fail(failed)
return
s.upgraded.complete()
proc onUpgrade*(s: Connection) {.async.} =
if not isNil(s.upgraded):
await s.upgraded
func shortLog*(conn: Connection): string =
if conn.isNil: "Connection(nil)"
elif conn.peerInfo.isNil: $conn.oid

View File

@ -244,10 +244,8 @@ proc upgradeIncoming(s: Switch, incomingConn: Connection) {.async, gcsafe.} = #
await ms.handle(cconn)
except CatchableError as exc:
debug "Exception in secure handler during incoming upgrade", msg = exc.msg, conn
if not isNil(cconn) and
not isNil(cconn.upgraded) and
not(cconn.upgraded.finished):
cconn.upgraded.fail(exc)
if not cconn.isUpgraded:
cconn.upgrade(exc)
finally:
if not isNil(cconn):
await cconn.close()
@ -265,10 +263,8 @@ proc upgradeIncoming(s: Switch, incomingConn: Connection) {.async, gcsafe.} = #
await ms.handle(incomingConn, active = true)
except CatchableError as exc:
debug "Exception upgrading incoming", exc = exc.msg
if not isNil(incomingConn) and
not isNil(incomingConn.upgraded) and
not(incomingConn.upgraded.finished):
incomingConn.upgraded.fail(exc)
if not incomingConn.isUpgraded:
incomingConn.upgrade(exc)
finally:
if not isNil(incomingConn):
await incomingConn.close()
@ -441,7 +437,7 @@ proc upgradeMonitor(conn: Connection, upgrades: AsyncSemaphore) {.async.} =
# upgrade, this timeout guarantees that a
# "hanged" remote doesn't hold the upgrade
# forever
await conn.upgraded.wait(30.seconds) # wait for connection to be upgraded
await conn.onUpgrade.wait(30.seconds) # wait for connection to be upgraded
trace "Connection upgrade succeeded"
except CatchableError as exc:
libp2p_failed_upgrades_incoming.inc()