From ac5288651c68bed9669d94b1a29641afca16d394 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Fri, 26 Mar 2021 11:53:03 +0100 Subject: [PATCH] Exception handling signatures (#97) Minimally work around leaking `Exception` for https://github.com/status-im/nim-chronos/pull/166 --- json_rpc/client.nim | 19 +++++++++++++------ json_rpc/clients/httpclient.nim | 3 ++- json_rpc/clients/socketclient.nim | 3 ++- json_rpc/clients/websocketclient.nim | 3 ++- json_rpc/router.nim | 5 ++++- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/json_rpc/client.nim b/json_rpc/client.nim index c871149..f729461 100644 --- a/json_rpc/client.nim +++ b/json_rpc/client.nim @@ -10,11 +10,12 @@ export type ClientId* = int64 + MethodHandler* = proc (j: JsonNode) {.gcsafe, raises: [Defect, CatchableError].} RpcClient* = ref object of RootRef awaiting*: Table[ClientId, Future[Response]] lastId: ClientId - methodHandlers: Table[string, proc(j: JsonNode) {.gcsafe.}] - onDisconnect*: proc() {.gcsafe.} + methodHandlers: Table[string, MethodHandler] + onDisconnect*: proc() {.gcsafe, raises: [Defect].} Response* = JsonNode @@ -26,10 +27,13 @@ proc rpcCallNode*(path: string, params: JsonNode, id: ClientId): JsonNode = %{"jsonrpc": %"2.0", "method": %path, "params": params, "id": %id} method call*(client: RpcClient, name: string, - params: JsonNode): Future[Response] {.gcsafe, async, base.} = + params: JsonNode): Future[Response] {. + base, async, gcsafe, raises: [Defect, CatchableError].} = discard -method close*(client: RpcClient) {.base, gcsafe, async.} = discard +method close*(client: RpcClient): Future[void] {. + base, async, gcsafe, raises: [Defect, CatchableError].} = + discard template `or`(a: JsonNode, b: typed): JsonNode = if a == nil: b else: a @@ -37,7 +41,10 @@ template `or`(a: JsonNode, b: typed): JsonNode = proc processMessage*(self: RpcClient, line: string) = # Note: this doesn't use any transport code so doesn't need to be # differentiated. - let node = parseJson(line) + let node = try: parseJson(line) + except CatchableError as exc: raise exc + # TODO https://github.com/status-im/nimbus-eth2/issues/2430 + except Exception as exc: raise (ref ValueError)(msg: exc.msg, parent: exc) if "id" in node: let id = node{"id"} or newJNull() @@ -164,7 +171,7 @@ proc processRpcSigs(clientType, parsedCode: NimNode): NimNode = var procDef = createRpcFromSig(clientType, line) result.add(procDef) -proc setMethodHandler*(cl: RpcClient, name: string, callback: proc(j: JsonNode) {.gcsafe.}) = +proc setMethodHandler*(cl: RpcClient, name: string, callback: MethodHandler) = cl.methodHandlers[name] = callback proc delMethodHandler*(cl: RpcClient, name: string) = diff --git a/json_rpc/clients/httpclient.nim b/json_rpc/clients/httpclient.nim index c5b587c..9a63bcc 100644 --- a/json_rpc/clients/httpclient.nim +++ b/json_rpc/clients/httpclient.nim @@ -170,7 +170,8 @@ proc httpMethod*(client: RpcHttpClient, m: HttpMethod) = client.options.httpMethod = m method call*(client: RpcHttpClient, name: string, - params: JsonNode): Future[Response] {.async, gcsafe.} = + params: JsonNode): Future[Response] {. + async, gcsafe, raises: [Defect, CatchableError].} = ## Remotely calls the specified RPC method. let id = client.getNextId() diff --git a/json_rpc/clients/socketclient.nim b/json_rpc/clients/socketclient.nim index d7a2cf3..c4468d9 100644 --- a/json_rpc/clients/socketclient.nim +++ b/json_rpc/clients/socketclient.nim @@ -18,7 +18,8 @@ proc newRpcSocketClient*: RpcSocketClient = RpcSocketClient.new() method call*(self: RpcSocketClient, name: string, - params: JsonNode): Future[Response] {.async.} = + params: JsonNode): Future[Response] {. + async, gcsafe, raises: [Defect, CatchableError].} = ## Remotely calls the specified RPC method. let id = self.getNextId() var value = $rpcCallNode(name, params, id) & "\r\n" diff --git a/json_rpc/clients/websocketclient.nim b/json_rpc/clients/websocketclient.nim index 6ea91d0..067242e 100644 --- a/json_rpc/clients/websocketclient.nim +++ b/json_rpc/clients/websocketclient.nim @@ -19,7 +19,8 @@ proc newRpcWebSocketClient*: RpcWebSocketClient = RpcWebSocketClient.new() method call*(self: RpcWebSocketClient, name: string, - params: JsonNode): Future[Response] {.async.} = + params: JsonNode): Future[Response] {. + async, gcsafe, raises: [Defect, CatchableError].} = ## Remotely calls the specified RPC method. let id = self.getNextId() var value = $rpcCallNode(name, params, id) & "\r\n" diff --git a/json_rpc/router.nim b/json_rpc/router.nim index 51f706a..e628292 100644 --- a/json_rpc/router.nim +++ b/json_rpc/router.nim @@ -10,7 +10,7 @@ type StringOfJson* = JsonString # Procedure signature accepted as an RPC call by server - RpcProc* = proc(input: JsonNode): Future[StringOfJson] {.gcsafe.} + RpcProc* = proc(input: JsonNode): Future[StringOfJson] {.gcsafe, raises: [Defect, CatchableError].} RpcRouter* = object procs*: Table[string, RpcProc] @@ -90,6 +90,9 @@ proc route*(router: RpcRouter, data: string): Future[string] {.async, gcsafe.} = try: parseJson(data) except CatchableError as err: return string(wrapError(JSON_PARSE_ERROR, err.msg)) + except Exception as err: + # TODO https://github.com/status-im/nimbus-eth2/issues/2430 + return string(wrapError(JSON_PARSE_ERROR, err.msg)) return string(await router.route(node))