don't crash on double peerinfo close (#167)

This commit is contained in:
Jacek Sieka 2020-05-11 21:05:24 +02:00 committed by GitHub
parent 3053f03814
commit 618e01eba3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 37 deletions

View File

@ -13,9 +13,7 @@ import peerinfo,
errors, errors,
multiaddress, multiaddress,
stream/lpstream, stream/lpstream,
peerinfo, peerinfo
varint,
vbuffer
export lpstream export lpstream
@ -64,18 +62,20 @@ proc setupConnectionTracker(): ConnectionTracker =
declareGauge libp2p_open_connection, "open Connection instances" declareGauge libp2p_open_connection, "open Connection instances"
proc `$`*(conn: Connection): string =
if not isNil(conn.peerInfo):
result = $(conn.peerInfo)
proc bindStreamClose(conn: Connection) {.async.} = proc bindStreamClose(conn: Connection) {.async.} =
# bind stream's close event to connection's close # bind stream's close event to connection's close
# to ensure correct close propagation # to ensure correct close propagation
if not isNil(conn.stream.closeEvent): if not isNil(conn.stream.closeEvent):
await conn.stream.closeEvent.wait() await conn.stream.closeEvent.wait()
trace "wrapped stream closed, about to close conn", closed = conn.isClosed, trace "wrapped stream closed, about to close conn",
peer = if not isNil(conn.peerInfo): closed = conn.isClosed, conn = $conn
conn.peerInfo.id else: ""
if not conn.isClosed: if not conn.isClosed:
trace "wrapped stream closed, closing conn", closed = conn.isClosed, trace "wrapped stream closed, closing conn",
peer = if not isNil(conn.peerInfo): closed = conn.isClosed, conn = $conn
conn.peerInfo.id else: ""
await conn.close() await conn.close()
proc init[T: Connection](self: var T, stream: LPStream): T = proc init[T: Connection](self: var T, stream: LPStream): T =
@ -119,36 +119,26 @@ method closed*(s: Connection): bool =
result = s.stream.closed result = s.stream.closed
method close*(s: Connection) {.async, gcsafe.} = method close*(s: Connection) {.async, gcsafe.} =
trace "about to close connection", closed = s.closed, trace "about to close connection", closed = s.closed, conn = $s
peer = if not isNil(s.peerInfo):
s.peerInfo.id else: ""
if not s.isClosed: if not s.isClosed:
s.isClosed = true s.isClosed = true
inc getConnectionTracker().closed inc getConnectionTracker().closed
if not isNil(s.stream) and not s.stream.closed: if not isNil(s.stream) and not s.stream.closed:
trace "closing child stream", closed = s.closed, trace "closing child stream", closed = s.closed, conn = $s
peer = if not isNil(s.peerInfo):
s.peerInfo.id else: ""
await s.stream.close() await s.stream.close()
s.closeEvent.fire() s.closeEvent.fire()
trace "waiting readloops", count=s.readLoops.len trace "waiting readloops", count=s.readLoops.len, conn = $s
let loopFuts = await allFinished(s.readLoops) let loopFuts = await allFinished(s.readLoops)
checkFutures(loopFuts) checkFutures(loopFuts)
s.readLoops = @[] s.readLoops = @[]
trace "connection closed", closed = s.closed, trace "connection closed", closed = s.closed, conn = $s
peer = if not isNil(s.peerInfo):
s.peerInfo.id else: ""
libp2p_open_connection.dec() libp2p_open_connection.dec()
method getObservedAddrs*(c: Connection): Future[MultiAddress] {.base, async, gcsafe.} = method getObservedAddrs*(c: Connection): Future[MultiAddress] {.base, async, gcsafe.} =
## get resolved multiaddresses for the connection ## get resolved multiaddresses for the connection
result = c.observedAddrs result = c.observedAddrs
proc `$`*(conn: Connection): string =
if not isNil(conn.peerInfo):
result = $(conn.peerInfo)

View File

@ -8,7 +8,7 @@
## those terms. ## those terms.
import options import options
import chronos import chronos, chronicles
import peer, multiaddress, crypto/crypto import peer, multiaddress, crypto/crypto
## A peer can be constructed in one of tree ways: ## A peer can be constructed in one of tree ways:
@ -35,6 +35,18 @@ type
of HasPublic: of HasPublic:
key: Option[PublicKey] key: Option[PublicKey]
proc id*(p: PeerInfo): string =
p.peerId.pretty()
proc `$`*(p: PeerInfo): string =
result.add(p.id)
result.add(" ")
result.add($p.addrs)
result.add(" ")
result.add($p.protocols)
template postInit(peerinfo: PeerInfo, template postInit(peerinfo: PeerInfo,
addrs: openarray[MultiAddress], addrs: openarray[MultiAddress],
protocols: openarray[string]) = protocols: openarray[string]) =
@ -71,7 +83,11 @@ proc init*(p: typedesc[PeerInfo], key: PublicKey,
result.postInit(addrs, protocols) result.postInit(addrs, protocols)
proc close*(p: PeerInfo) {.inline.} = proc close*(p: PeerInfo) {.inline.} =
if not p.lifefut.finished:
p.lifefut.complete() p.lifefut.complete()
else:
# TODO this should ideally not happen
notice "Closing closed peer", peer = p.id
proc join*(p: PeerInfo): Future[void] {.inline.} = proc join*(p: PeerInfo): Future[void] {.inline.} =
var retFuture = newFuture[void]() var retFuture = newFuture[void]()
@ -103,15 +119,3 @@ proc publicKey*(p: PeerInfo): Option[PublicKey] {.inline.} =
result = p.key result = p.key
else: else:
result = some(p.privateKey.getKey()) result = some(p.privateKey.getKey())
proc id*(p: PeerInfo): string {.inline.} =
p.peerId.pretty()
proc `$`*(p: PeerInfo): string =
result.add(p.id)
result.add(" ")
result.add($p.addrs)
result.add(" ")
result.add($p.protocols)