Skip to content

Commit

Permalink
Propagate error parent (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
nitely authored Dec 19, 2024
1 parent b0a1ba7 commit 3e8f168
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 119 deletions.
8 changes: 4 additions & 4 deletions src/hyperx/client.nim
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export
HyperxConnError,
HyperxStrmError,
HyperxError,
isGracefulClose
isGracefulClose,
trace

var sslContext {.threadvar.}: SslContext

Expand All @@ -57,9 +58,8 @@ when not defined(hyperxTest):
if ssl:
wrapSocket(defaultSslContext(), result)
except CatchableError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
raise newConnError(err.msg)
debugErr2 err
raise newConnError(err.msg, err)

proc newClient*(
hostname: string,
Expand Down
125 changes: 47 additions & 78 deletions src/hyperx/clientserver.nim
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,14 @@ proc defaultSslContext*(
keyFile = keyFile
)
except CatchableError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
raise newConnError(err.msg)
debugErr2 err
raise newConnError(err.msg, err)
except Defect as err:
raise err
except Exception as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
# workaround for newContext raising Exception
raise newException(Defect, err.msg)
raise newException(Defect, err.msg, err)
doAssert result != nil, "failure to initialize the SSL context"
# https://httpwg.org/specs/rfc9113.html#tls12features
const ctxOps = SSL_OP_ALL or
Expand Down Expand Up @@ -184,15 +182,13 @@ proc close*(client: ClientContext) {.raises: [HyperxConnError].} =
try:
client.sock.close()
except CatchableError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
raise newConnError(err.msg)
debugErr2 err
raise newConnError(err.msg, err)
except Defect as err:
raise err # raise original error
raise err
except Exception as err:
debugInfo err.getStackTrace()
debugInfo err.msg
raise newException(Defect, err.msg)
debugErr2 err
raise newException(Defect, err.msg, err)
finally:
client.recvMsgs.close()
client.streamOpenedMsgs.close()
Expand Down Expand Up @@ -296,9 +292,9 @@ func hpackDecode(
# can resize multiple times before a header, but not after
canResize = false
doAssert i == L
except HpackError:
debugInfo getCurrentException().msg
raise newConnError(hyxCompressionError)
except HpackError as err:
debugErr2 err
raise newConnError(hyxCompressionError, parent=err)

func hpackEncode*(
client: ClientContext,
Expand All @@ -310,9 +306,8 @@ func hpackEncode*(
try:
discard hencode(name, value, client.headersEnc, payload, huffman = false)
except HpackError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
raise newConnError(err.msg)
debugErr2 err
raise newConnError(err.msg, err)

proc sendNaked(client: ClientContext, frm: Frame) {.async.} =
debugInfo "===SENT==="
Expand All @@ -335,18 +330,16 @@ proc send(client: ClientContext, frm: Frame) {.async.} =
try:
await client.sendNaked(frm)
except HyperxConnError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
client.error ?= newError err
client.close()
raise err
except OsError, SslError:
let err = getCurrentException()
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
client.error ?= newConnError(err.msg)
client.close()
raise newConnError(err.msg)
raise newConnError(err.msg, err)

proc sendSilently(client: ClientContext, frm: Frame) {.async.} =
## Call this to send within an except
Expand All @@ -358,8 +351,7 @@ proc sendSilently(client: ClientContext, frm: Frame) {.async.} =
try:
await client.sendNaked(frm)
except HyperxError, OsError, SslError:
debugInfo getCurrentException().getStackTrace()
debugInfo getCurrentException().msg
debugErr getCurrentException()

func handshakeBlob(typ: ClientTyp): string {.compileTime.} =
result = ""
Expand Down Expand Up @@ -406,13 +398,12 @@ proc handshake(client: ClientContext) {.async.} =
await client.handshakeNaked()
except OsError, SslError:
let err = getCurrentException()
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
doAssert client.isConnected
# XXX err.msg includes a traceback for SslError but it should not
client.error ?= newConnError(err.msg)
client.close()
raise newConnError(err.msg)
raise newConnError(err.msg, err)

func doTransitionRecv(
s: Stream, frm: Frame
Expand Down Expand Up @@ -522,22 +513,19 @@ proc recvTask(client: ClientContext) {.async.} =
except QueueClosedError:
doAssert not client.isConnected
except HyperxConnError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
client.error ?= newError err
await client.sendSilently newGoAwayFrame(
client.maxPeerStreamIdSeen, err.code
)
raise err
except OsError, SslError:
let err = getCurrentException()
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
client.error ?= newConnError(err.msg)
raise newConnError(err.msg)
raise newConnError(err.msg, err)
except CatchableError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
raise err
finally:
debugInfo "recvTask exited"
Expand Down Expand Up @@ -709,20 +697,17 @@ proc recvDispatcher(client: ClientContext) {.async.} =
except QueueClosedError:
doAssert not client.isConnected
except HyperxConnError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
client.error ?= newError err
await client.sendSilently newGoAwayFrame(
client.maxPeerStreamIdSeen, err.code
)
raise err
except HyperxStrmError:
debugInfo getCurrentException().getStackTrace()
debugInfo getCurrentException().msg
debugErr getCurrentException()
doAssert false
except CatchableError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
raise err
finally:
debugInfo "responseDispatcher exited"
Expand All @@ -745,13 +730,11 @@ proc windowUpdateTask(client: ClientContext) {.async.} =
except QueueClosedError:
doAssert not client.isConnected
except HyperxConnError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
client.error ?= newError err
raise err
except CatchableError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
raise err
finally:
debugInfo "windowUpdateTask exited"
Expand All @@ -761,9 +744,8 @@ proc connect(client: ClientContext) {.async.} =
try:
await client.sock.connect(client.hostname, client.port)
except OsError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
raise newConnError(err.msg)
debugErr2 err
raise newConnError(err.msg, err)

proc failSilently(f: Future[void]) {.async.} =
## Be careful when wrapping non {.async.} procs,
Expand All @@ -773,7 +755,7 @@ proc failSilently(f: Future[void]) {.async.} =
try:
await f
except HyperxError:
debugInfo getCurrentException().msg
debugErr getCurrentException()

template with*(client: ClientContext, body: untyped): untyped =
doAssert not client.isConnected
Expand Down Expand Up @@ -959,10 +941,9 @@ proc recvHeadersTaskNaked(strm: ClientStream) {.async.} =
strm.headersRecv.add frm.payload
try:
strm.contentLen = contentLen(frm.payload)
except ValueError:
debugInfo getCurrentException().getStackTrace()
debugInfo getCurrentException().msg
raise newStrmError(hyxProtocolError)
except ValueError as err:
debugErr2 err
raise newStrmError(hyxProtocolError, parent=err)
if frmfEndStream in frm.flags:
# XXX dont do for no content status 1xx/204/304 and HEAD response
if strm.client.typ == ctServer:
Expand Down Expand Up @@ -1019,24 +1000,21 @@ proc recvTask(strm: ClientStream) {.async.} =
except QueueClosedError:
discard
except HyperxConnError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
client.error ?= newError err
await client.sendSilently newGoAwayFrame(
client.maxPeerStreamIdSeen, err.code
)
client.close()
raise err
except HyperxStrmError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
stream.error = newError err
if err.typ == hyxLocalErr:
await failSilently strm.writeRst(err.code)
raise err
except CatchableError as err:
debugInfo err.getStackTrace()
debugInfo err.msg
debugErr2 err
raise err
finally:
strm.close()
Expand All @@ -1051,14 +1029,11 @@ proc recvHeaders*(strm: ClientStream, data: ref string) {.async.} =
try:
await recvHeadersNaked(strm, data)
except QueueClosedError as err:
debugErr2 err
if strm.client.error != nil:
debugInfo strm.client.error.getStackTrace()
debugInfo strm.client.error.msg
raise newError strm.client.error
raise newError(strm.client.error, err)
if strm.stream.error != nil:
debugInfo strm.stream.error.getStackTrace()
debugInfo strm.stream.error.msg
raise newError strm.stream.error
raise newError(strm.stream.error, err)
raise err

proc recvBodyNaked(strm: ClientStream, data: ref string) {.async.} =
Expand Down Expand Up @@ -1091,14 +1066,11 @@ proc recvBody*(strm: ClientStream, data: ref string) {.async.} =
try:
await recvBodyNaked(strm, data)
except QueueClosedError as err:
debugErr2 err
if strm.client.error != nil:
debugInfo strm.client.error.getStackTrace()
debugInfo strm.client.error.msg
raise newError strm.client.error
raise newError(strm.client.error, err)
if strm.stream.error != nil:
debugInfo strm.stream.error.getStackTrace()
debugInfo strm.stream.error.msg
raise newError strm.stream.error
raise newError(strm.stream.error, err)
raise err

func recvTrailers*(strm: ClientStream): string =
Expand Down Expand Up @@ -1190,14 +1162,11 @@ proc sendBody*(
try:
await sendBodyNaked(strm, data, finish)
except QueueClosedError as err:
debugErr2 err
if strm.client.error != nil:
debugInfo strm.client.error.getStackTrace()
debugInfo strm.client.error.msg
raise newError strm.client.error
raise newError(strm.client.error, err)
if strm.stream.error != nil:
debugInfo strm.stream.error.getStackTrace()
debugInfo strm.stream.error.msg
raise newError strm.stream.error
raise newError(strm.stream.error, err)
raise err

template with*(strm: ClientStream, body: untyped): untyped =
Expand Down
28 changes: 18 additions & 10 deletions src/hyperx/errors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,16 @@ type
func newConnClosedError*: ref ConnClosedError {.raises: [].} =
result = (ref ConnClosedError)(typ: hyxLocalErr, code: hyxInternalError, msg: "Connection Closed")

func newConnError*(msg: string): ref HyperxConnError {.raises: [].} =
result = (ref HyperxConnError)(typ: hyxLocalErr, code: hyxInternalError, msg: msg)
func newConnError*(msg: string, parent: ref Exception = nil): ref HyperxConnError {.raises: [].} =
result = (ref HyperxConnError)(
typ: hyxLocalErr, code: hyxInternalError, msg: msg, parent: parent
)

func newConnError*(
errCode: HyperxErrCode, typ = hyxLocalErr
errCode: HyperxErrCode, typ = hyxLocalErr, parent: ref Exception = nil
): ref HyperxConnError {.raises: [].} =
result = (ref HyperxConnError)(
typ: typ, code: errCode, msg: "Connection Error: " & $errCode
typ: typ, code: errCode, msg: "Connection Error: " & $errCode, parent: parent
)

func newConnError*(
Expand All @@ -81,27 +83,33 @@ func newConnError*(
msg: "Connection Error: " & $errCode.toErrorCode
)

func newError*(err: ref HyperxConnError): ref HyperxConnError {.raises: [].} =
func newError*(
err: ref HyperxConnError, parent: ref Exception = nil
): ref HyperxConnError {.raises: [].} =
result = (ref HyperxConnError)(
typ: err.typ, code: err.code, msg: err.msg
typ: err.typ, code: err.code, msg: err.msg, parent: parent
)

func newStrmError*(
errCode: HyperxErrCode, typ = hyxLocalErr
errCode: HyperxErrCode, typ = hyxLocalErr, parent: ref Exception = nil
): ref HyperxStrmError {.raises: [].} =
let msg = case typ
of hyxLocalErr: "Stream Error: " & $errCode
of hyxRemoteErr: "Got Rst Error: " & $errCode
result = (ref HyperxStrmError)(typ: typ, code: errCode, msg: msg)
result = (ref HyperxStrmError)(
typ: typ, code: errCode, msg: msg, parent: parent
)

func newStrmError*(
errCode: uint32, typ = hyxLocalErr
): ref HyperxStrmError {.raises: [].} =
result = newStrmError(errCode.toErrorCode, typ)

func newError*(err: ref HyperxStrmError): ref HyperxStrmError {.raises: [].} =
func newError*(
err: ref HyperxStrmError, parent: ref Exception = nil
): ref HyperxStrmError {.raises: [].} =
result = (ref HyperxStrmError)(
typ: err.typ, code: err.code, msg: err.msg
typ: err.typ, code: err.code, msg: err.msg, parent: parent
)

func newErrorOrDefault*(
Expand Down
Loading

0 comments on commit 3e8f168

Please sign in to comment.