mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-27 09:01:37 +00:00
fixes #22122 The root cause is in the effect tracker: raise was recording the whole conditional expression as one exception source, so semantic checking only saw the widened common base type instead of the concrete exception classes from each branch.
74 lines
2.3 KiB
Nim
74 lines
2.3 KiB
Nim
from std/os import osLastError, osErrorMsg, OSErrorCode, raiseOSError,
|
|
newOSError, `==`
|
|
|
|
{.push raises: [].}
|
|
|
|
const
|
|
EPERM* = OSErrorCode(1)
|
|
ECONNABORTED* = OSErrorCode(53)
|
|
ETIMEDOUT* = OSErrorCode(60)
|
|
ENOTCONN* = OSErrorCode(107)
|
|
EMFILE* = OSErrorCode(24)
|
|
ENFILE* = OSErrorCode(23)
|
|
ENOBUFS* = OSErrorCode(55)
|
|
ENOMEM* = OSErrorCode(12)
|
|
|
|
type
|
|
AsyncError* = object of CatchableError
|
|
TransportErrorBase* = object of AsyncError
|
|
TransportOsError* = object of TransportErrorBase
|
|
code*: OSErrorCode
|
|
TransportTooManyError* = object of TransportErrorBase
|
|
TransportAbortedError* = object of TransportErrorBase
|
|
|
|
template getConnectionAbortedError*(
|
|
code: OSErrorCode
|
|
): ref TransportAbortedError =
|
|
let msg =
|
|
case code
|
|
of OSErrorCode(0), ECONNABORTED:
|
|
"[ECONNABORTED] Connection has been aborted before being accepted"
|
|
of EPERM:
|
|
"[EPERM] Firewall rules forbid connection"
|
|
of ETIMEDOUT:
|
|
"[ETIMEDOUT] Operation has been timed out"
|
|
of ENOTCONN:
|
|
"[ENOTCONN] Transport endpoint is not connected"
|
|
else:
|
|
"[" & $int(code) & "] Connection has been aborted"
|
|
newException(TransportAbortedError, msg)
|
|
|
|
template getTransportTooManyError*(
|
|
code = OSErrorCode(0)
|
|
): ref TransportTooManyError =
|
|
let msg =
|
|
case code
|
|
of OSErrorCode(0):
|
|
"Too many open transports"
|
|
of EMFILE:
|
|
"[EMFILE] Too many open files in the process"
|
|
of ENFILE:
|
|
"[ENFILE] Too many open files in system"
|
|
of ENOBUFS:
|
|
"[ENOBUFS] No buffer space available"
|
|
of ENOMEM:
|
|
"[ENOMEM] Not enough memory availble"
|
|
else:
|
|
"[" & $int(code) & "] Too many open transports"
|
|
newException(TransportTooManyError, msg)
|
|
|
|
template getTransportError*(ecode: OSErrorCode): untyped =
|
|
case ecode
|
|
of ECONNABORTED, EPERM, ETIMEDOUT, ENOTCONN:
|
|
getConnectionAbortedError(ecode)
|
|
of EMFILE, ENFILE, ENOBUFS, ENOMEM:
|
|
getTransportTooManyError(ecode)
|
|
else:
|
|
(ref TransportOsError)(code: ecode,
|
|
msg: "(" & $int(ecode) & ") " & osErrorMsg(ecode))
|
|
|
|
proc raiseTransportError*(err: OSErrorCode) {.
|
|
raises: [TransportAbortedError, TransportTooManyError, TransportOsError],
|
|
noreturn.} =
|
|
## Raises transport specific OS error.
|
|
raise getTransportError(err) |