Chronos strict exception tracking (#652)

* Enable chronos strict exception tracking ( -d:chronosStrictException )
This commit is contained in:
Tanguy 2022-01-05 16:27:33 +01:00 committed by GitHub
parent dffe4bed45
commit f3dee6865c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 71 additions and 38 deletions

View File

@ -2,7 +2,7 @@ asynctest;https://github.com/markspanbroek/asynctest@#3882ed64ed3159578f796bc5ae
bearssl;https://github.com/status-im/nim-bearssl@#ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7 bearssl;https://github.com/status-im/nim-bearssl@#ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7
chronicles;https://github.com/status-im/nim-chronicles@#2a2681b60289aaf7895b7056f22616081eb1a882 chronicles;https://github.com/status-im/nim-chronicles@#2a2681b60289aaf7895b7056f22616081eb1a882
chronos;https://github.com/status-im/nim-chronos@#7dc58d42b6905a7fd7531875fa76060f8f744e4e chronos;https://github.com/status-im/nim-chronos@#7dc58d42b6905a7fd7531875fa76060f8f744e4e
dnsclient;https://github.com/ba0f3/dnsclient.nim@#536cc6b7933e5f86590bb27083c0ffeab31255f9 dnsclient;https://github.com/ba0f3/dnsclient.nim@#fbb76f8af8a33ab818184a7d4406d9fee20993be
faststreams;https://github.com/status-im/nim-faststreams@#c653d05f277dca0f374732c5b9b80f2368faea33 faststreams;https://github.com/status-im/nim-faststreams@#c653d05f277dca0f374732c5b9b80f2368faea33
httputils;https://github.com/status-im/nim-http-utils@#507bfb7dcb6244d76ce2567df7bf3756cbe88775 httputils;https://github.com/status-im/nim-http-utils@#507bfb7dcb6244d76ce2567df7bf3756cbe88775
json_serialization;https://github.com/status-im/nim-json-serialization@#010aa238cf6afddf1fbe4cbcd27ab3be3f443841 json_serialization;https://github.com/status-im/nim-json-serialization@#010aa238cf6afddf1fbe4cbcd27ab3be3f443841

View File

@ -162,7 +162,10 @@ proc main() {.async.} =
stdinReader = fromPipe(rfd) stdinReader = fromPipe(rfd)
var thread: Thread[AsyncFD] var thread: Thread[AsyncFD]
thread.createThread(readInput, wfd) try:
thread.createThread(readInput, wfd)
except Exception as exc:
quit("Failed to create thread: " & exc.msg)
var localAddress = MultiAddress.init(DefaultAddr).tryGet() var localAddress = MultiAddress.init(DefaultAddr).tryGet()

View File

@ -9,7 +9,7 @@ skipDirs = @["tests", "examples", "Nim", "tools", "scripts", "docs"]
requires "nim >= 1.2.0", requires "nim >= 1.2.0",
"nimcrypto >= 0.4.1", "nimcrypto >= 0.4.1",
"https://github.com/ba0f3/dnsclient.nim == 0.1.0", "dnsclient >= 0.1.2",
"bearssl >= 0.1.4", "bearssl >= 0.1.4",
"chronicles >= 0.10.2", "chronicles >= 0.10.2",
"chronos >= 3.0.6", "chronos >= 3.0.6",
@ -18,11 +18,19 @@ requires "nim >= 1.2.0",
"stew#head", "stew#head",
"websock" "websock"
const nimflags =
"--verbosity:0 --hints:off " &
"--warning[CaseTransition]:off --warning[ObservableStores]:off " &
"--warning[LockLevel]:off " &
"-d:chronosStrictException " &
"--styleCheck:usages --styleCheck:hint "
proc runTest(filename: string, verify: bool = true, sign: bool = true, proc runTest(filename: string, verify: bool = true, sign: bool = true,
moreoptions: string = "") = moreoptions: string = "") =
let env_nimflags = getEnv("NIMFLAGS") let env_nimflags = getEnv("NIMFLAGS")
var excstr = "nim c --opt:speed -d:debug -d:libp2p_agents_metrics -d:libp2p_protobuf_metrics -d:libp2p_network_protocols_metrics --verbosity:0 --hints:off --styleCheck:usages --styleCheck:hint " & env_nimflags var excstr = "nim c --opt:speed -d:debug -d:libp2p_agents_metrics -d:libp2p_protobuf_metrics -d:libp2p_network_protocols_metrics "
excstr.add(" --warning[CaseTransition]:off --warning[ObservableStores]:off --warning[LockLevel]:off") excstr.add(" " & env_nimflags & " ")
excstr.add(" " & nimflags & " ")
excstr.add(" -d:libp2p_pubsub_sign=" & $sign) excstr.add(" -d:libp2p_pubsub_sign=" & $sign)
excstr.add(" -d:libp2p_pubsub_verify=" & $verify) excstr.add(" -d:libp2p_pubsub_verify=" & $verify)
excstr.add(" " & moreoptions & " ") excstr.add(" " & moreoptions & " ")
@ -34,8 +42,8 @@ proc runTest(filename: string, verify: bool = true, sign: bool = true,
rmFile "tests/" & filename.toExe rmFile "tests/" & filename.toExe
proc buildSample(filename: string, run = false) = proc buildSample(filename: string, run = false) =
var excstr = "nim c --opt:speed --threads:on -d:debug --verbosity:0 --hints:off " var excstr = "nim c --opt:speed --threads:on -d:debug "
excstr.add(" --warning[CaseTransition]:off --warning[ObservableStores]:off --warning[LockLevel]:off") excstr.add(" " & nimflags & " ")
excstr.add(" examples/" & filename) excstr.add(" examples/" & filename)
exec excstr exec excstr
if run: if run:
@ -44,7 +52,7 @@ proc buildSample(filename: string, run = false) =
proc buildTutorial(filename: string) = proc buildTutorial(filename: string) =
discard gorge "cat " & filename & " | nim c -r --hints:off tools/markdown_runner.nim | " & discard gorge "cat " & filename & " | nim c -r --hints:off tools/markdown_runner.nim | " &
" nim --warning[CaseTransition]:off --warning[ObservableStores]:off --warning[LockLevel]:off c -" " nim " & nimflags & " c -"
task testnative, "Runs libp2p native tests": task testnative, "Runs libp2p native tests":
runTest("testnative") runTest("testnative")

View File

@ -65,7 +65,7 @@ type
discard discard
PeerEventHandler* = PeerEventHandler* =
proc(peerId: PeerId, event: PeerEvent): Future[void] {.gcsafe.} proc(peerId: PeerId, event: PeerEvent): Future[void] {.gcsafe, raises: [Defect].}
MuxerHolder = object MuxerHolder = object
muxer: Muxer muxer: Muxer

View File

@ -150,10 +150,10 @@ type
key*: PublicKey key*: PublicKey
P2PStreamCallback* = proc(api: DaemonAPI, P2PStreamCallback* = proc(api: DaemonAPI,
stream: P2PStream): Future[void] {.gcsafe.} stream: P2PStream): Future[void] {.gcsafe, raises: [Defect, CatchableError].}
P2PPubSubCallback* = proc(api: DaemonAPI, P2PPubSubCallback* = proc(api: DaemonAPI,
ticket: PubsubTicket, ticket: PubsubTicket,
message: PubSubMessage): Future[bool] {.gcsafe.} message: PubSubMessage): Future[bool] {.gcsafe, raises: [Defect, CatchableError].}
DaemonError* = object of LPError DaemonError* = object of LPError
DaemonRemoteError* = object of DaemonError DaemonRemoteError* = object of DaemonError
@ -755,7 +755,13 @@ proc newDaemonApi*(flags: set[P2PDaemonFlags] = {},
# Starting daemon process # Starting daemon process
# echo "Starting ", cmd, " ", args.join(" ") # echo "Starting ", cmd, " ", args.join(" ")
api.process = startProcess(cmd, "", args, env, {poParentStreams}) api.process =
try:
startProcess(cmd, "", args, env, {poParentStreams})
except CatchableError as exc:
raise exc
except Exception as exc:
raiseAssert exc.msg
# Waiting until daemon will not be bound to control socket. # Waiting until daemon will not be bound to control socket.
while true: while true:
if not api.process.running(): if not api.process.running():
@ -900,7 +906,7 @@ proc openStream*(api: DaemonAPI, peer: PeerId,
stream.flags.incl(Outbound) stream.flags.incl(Outbound)
stream.transp = transp stream.transp = transp
result = stream result = stream
except Exception as exc: except CatchableError as exc:
await api.closeConnection(transp) await api.closeConnection(transp)
raise exc raise exc
@ -936,7 +942,7 @@ proc addHandler*(api: DaemonAPI, protocols: seq[string],
protocols)) protocols))
pb.withMessage() do: pb.withMessage() do:
api.servers.add(P2PServer(server: server, address: maddress)) api.servers.add(P2PServer(server: server, address: maddress))
except Exception as exc: except CatchableError as exc:
for item in protocols: for item in protocols:
api.handlers.del(item) api.handlers.del(item)
server.stop() server.stop()
@ -1301,7 +1307,7 @@ proc pubsubSubscribe*(api: DaemonAPI, topic: string,
ticket.transp = transp ticket.transp = transp
asyncSpawn pubsubLoop(api, ticket) asyncSpawn pubsubLoop(api, ticket)
result = ticket result = ticket
except Exception as exc: except CatchableError as exc:
await api.closeConnection(transp) await api.closeConnection(transp)
raise exc raise exc

View File

@ -49,7 +49,7 @@ proc allFuturesThrowing*[T](args: varargs[Future[T]]): Future[void] =
for fut in args: for fut in args:
futs &= fut futs &= fut
proc call() {.async.} = proc call() {.async.} =
var first: ref Exception = nil var first: ref CatchableError = nil
futs = await allFinished(futs) futs = await allFinished(futs)
for fut in futs: for fut in futs:
if fut.failed: if fut.failed:

View File

@ -78,7 +78,12 @@ proc getDnsResponse(
dataStream = newStringStream() dataStream = newStringStream()
dataStream.writeData(addr rawResponse[0], rawResponse.len) dataStream.writeData(addr rawResponse[0], rawResponse.len)
dataStream.setPosition(0) dataStream.setPosition(0)
# parseResponse can has a raises: [Exception, ..] because of
# https://github.com/nim-lang/Nim/commit/035134de429b5d99c5607c5fae912762bebb6008
# it can't actually raise though
return parseResponse(dataStream) return parseResponse(dataStream)
except CatchableError as exc: raise exc
except Exception as exc: raiseAssert exc.msg
finally: finally:
await sock.closeWait() await sock.closeWait()

View File

@ -7,6 +7,8 @@
## This file may not be copied, modified, or distributed except according to ## This file may not be copied, modified, or distributed except according to
## those terms. ## those terms.
{.push raises: [Defect].}
import chronos, chronicles, bearssl import chronos, chronicles, bearssl
import ../protobuf/minprotobuf, import ../protobuf/minprotobuf,
../peerinfo, ../peerinfo,

View File

@ -225,7 +225,7 @@ method accept*(self: TcpTransport): Future[Connection] {.async, gcsafe.} =
debug "Server was closed", exc = exc.msg debug "Server was closed", exc = exc.msg
raise newTransportClosedError(exc) raise newTransportClosedError(exc)
except CancelledError as exc: except CancelledError as exc:
raise raise exc
except CatchableError as exc: except CatchableError as exc:
debug "Unexpected error accepting connection", exc = exc.msg debug "Unexpected error accepting connection", exc = exc.msg
raise exc raise exc

View File

@ -11,7 +11,7 @@ import ../libp2p/[stream/connection,
import ./helpers import ./helpers
type TransportProvider* = proc(): Transport {.gcsafe.} type TransportProvider* = proc(): Transport {.gcsafe, raises: [Defect].}
proc commonTransportTest*(name: string, prov: TransportProvider, ma: string) = proc commonTransportTest*(name: string, prov: TransportProvider, ma: string) =
suite name & " common tests": suite name & " common tests":

View File

@ -13,6 +13,8 @@ import ../libp2p/protocols/secure/secure
import ./asyncunit import ./asyncunit
export asyncunit export asyncunit
{.push raises: [Defect].}
const const
StreamTransportTrackerName = "stream.transport" StreamTransportTrackerName = "stream.transport"
StreamServerTrackerName = "stream.server" StreamServerTrackerName = "stream.server"
@ -51,7 +53,9 @@ template checkTrackers*() =
checkpoint tracker.dump() checkpoint tracker.dump()
fail() fail()
# Also test the GC is not fooling with us # Also test the GC is not fooling with us
GC_fullCollect() try:
GC_fullCollect()
except: discard
type RngWrap = object type RngWrap = object
rng: ref BrHmacDrbgContext rng: ref BrHmacDrbgContext

View File

@ -10,6 +10,9 @@ import ../libp2p/errors,
../libp2p/protocols/protocol, ../libp2p/protocols/protocol,
../libp2p/upgrademngrs/upgrade ../libp2p/upgrademngrs/upgrade
{.push raises: [Defect].}
import ./helpers import ./helpers
when defined(nimHasUsed): {.used.} when defined(nimHasUsed): {.used.}
@ -53,7 +56,7 @@ method readOnce*(s: TestSelectStream,
method write*(s: TestSelectStream, msg: seq[byte]) {.async, gcsafe.} = discard method write*(s: TestSelectStream, msg: seq[byte]) {.async, gcsafe.} = discard
method close(s: TestSelectStream) {.async, gcsafe.} = method close(s: TestSelectStream) {.async, gcsafe, raises: [Defect].} =
s.isClosed = true s.isClosed = true
s.isEof = true s.isEof = true
@ -63,7 +66,7 @@ proc newTestSelectStream(): TestSelectStream =
## Mock stream for handles `ls` test ## Mock stream for handles `ls` test
type type
LsHandler = proc(procs: seq[byte]): Future[void] {.gcsafe.} LsHandler = proc(procs: seq[byte]): Future[void] {.gcsafe, raises: [Defect].}
TestLsStream = ref object of Connection TestLsStream = ref object of Connection
step*: int step*: int
@ -115,7 +118,7 @@ proc newTestLsStream(ls: LsHandler): TestLsStream {.gcsafe.} =
## Mock stream for handles `na` test ## Mock stream for handles `na` test
type type
NaHandler = proc(procs: string): Future[void] {.gcsafe.} NaHandler = proc(procs: string): Future[void] {.gcsafe, raises: [Defect].}
TestNaStream = ref object of Connection TestNaStream = ref object of Connection
step*: int step*: int
@ -195,14 +198,14 @@ suite "Multistream select":
asyncTest "test handle `ls`": asyncTest "test handle `ls`":
let ms = MultistreamSelect.new() let ms = MultistreamSelect.new()
proc testLsHandler(proto: seq[byte]) {.async, gcsafe.} # forward declaration var conn: Connection = nil
let conn = Connection(newTestLsStream(testLsHandler))
let done = newFuture[void]() let done = newFuture[void]()
proc testLsHandler(proto: seq[byte]) {.async, gcsafe.} = proc testLsHandler(proto: seq[byte]) {.async, gcsafe.} =
var strProto: string = string.fromBytes(proto) var strProto: string = string.fromBytes(proto)
check strProto == "\x26/test/proto1/1.0.0\n/test/proto2/1.0.0\n" check strProto == "\x26/test/proto1/1.0.0\n/test/proto2/1.0.0\n"
await conn.close() await conn.close()
done.complete() done.complete()
conn = Connection(newTestLsStream(testLsHandler))
proc testHandler(conn: Connection, proto: string): Future[void] proc testHandler(conn: Connection, proto: string): Future[void]
{.async, gcsafe.} = discard {.async, gcsafe.} = discard
@ -216,13 +219,12 @@ suite "Multistream select":
asyncTest "test handle `na`": asyncTest "test handle `na`":
let ms = MultistreamSelect.new() let ms = MultistreamSelect.new()
proc testNaHandler(msg: string): Future[void] {.async, gcsafe.} var conn: Connection = nil
let conn = newTestNaStream(testNaHandler)
proc testNaHandler(msg: string): Future[void] {.async, gcsafe.} = proc testNaHandler(msg: string): Future[void] {.async, gcsafe.} =
echo msg echo msg
check msg == Na check msg == Na
await conn.close() await conn.close()
conn = newTestNaStream(testNaHandler)
var protocol: LPProtocol = new LPProtocol var protocol: LPProtocol = new LPProtocol
proc testHandler(conn: Connection, proc testHandler(conn: Connection,

View File

@ -40,7 +40,7 @@ const
type type
TestProto = ref object of LPProtocol TestProto = ref object of LPProtocol
method init(p: TestProto) {.gcsafe.} = method init(p: TestProto) {.gcsafe, raises: [Defect].} =
proc handle(conn: Connection, proto: string) {.async, gcsafe.} = proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
let msg = string.fromBytes(await conn.readLp(1024)) let msg = string.fromBytes(await conn.readLp(1024))
check "Hello!" == msg check "Hello!" == msg

View File

@ -13,7 +13,7 @@ import ../libp2p/[stream/connection,
import ./helpers, ./commontransport import ./helpers, ./commontransport
const const
SecureKey* = """ SecureKey = """
-----BEGIN PRIVATE KEY----- -----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAP0yH7F7FtGunC91 MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAP0yH7F7FtGunC91
IPkU+u8B4gdxiwYW0J3PrixtB1Xz3e4dfjwQqhIJlG6BxQ4myCxmSPjxP/eOOYp+ IPkU+u8B4gdxiwYW0J3PrixtB1Xz3e4dfjwQqhIJlG6BxQ4myCxmSPjxP/eOOYp+
@ -32,7 +32,7 @@ NABr5ec1FxuJa/8=
-----END PRIVATE KEY----- -----END PRIVATE KEY-----
""" """
SecureCert* = """ SecureCert = """
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIICjDCCAfWgAwIBAgIURjeiJmkNbBVktqXvnXh44DKx364wDQYJKoZIhvcNAQEL MIICjDCCAfWgAwIBAgIURjeiJmkNbBVktqXvnXh44DKx364wDQYJKoZIhvcNAQEL
BQAwVzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM BQAwVzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
@ -62,13 +62,16 @@ suite "WebSocket transport":
commonTransportTest( commonTransportTest(
"WebSocket Secure", "WebSocket Secure",
proc (): Transport = (proc (): Transport {.gcsafe.} =
WsTransport.new( try:
Upgrade(), return WsTransport.new(
TLSPrivateKey.init(SecureKey), Upgrade(),
TLSCertificate.init(SecureCert), TLSPrivateKey.init(SecureKey),
{TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName}), TLSCertificate.init(SecureCert),
"/ip4/0.0.0.0/tcp/0/wss") {TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName})
except Exception: check(false)
),
"/ip4/0.0.0.0/tcp/0/wss")
asyncTest "Hostname verification": asyncTest "Hostname verification":
let ma = @[MultiAddress.init("/ip4/0.0.0.0/tcp/0/wss").tryGet()] let ma = @[MultiAddress.init("/ip4/0.0.0.0/tcp/0/wss").tryGet()]