Sockets now save a copy of osLastError to work around #2191.
This commit is contained in:
parent
c3244ef1ff
commit
a853d9c3e3
1 changed files with 22 additions and 4 deletions
|
|
@ -60,7 +60,8 @@ type
|
||||||
sslHasPeekChar: bool
|
sslHasPeekChar: bool
|
||||||
sslPeekChar: char
|
sslPeekChar: char
|
||||||
of false: nil
|
of false: nil
|
||||||
|
lastError: OSErrorCode ## stores the last error on this socket
|
||||||
|
|
||||||
Socket* = ref SocketImpl
|
Socket* = ref SocketImpl
|
||||||
|
|
||||||
SOBool* = enum ## Boolean socket options.
|
SOBool* = enum ## Boolean socket options.
|
||||||
|
|
@ -231,6 +232,15 @@ when defined(ssl):
|
||||||
if SSLSetFd(socket.sslHandle, socket.fd) != 1:
|
if SSLSetFd(socket.sslHandle, socket.fd) != 1:
|
||||||
raiseSSLError()
|
raiseSSLError()
|
||||||
|
|
||||||
|
proc getSocketError*(socket: Socket): OSErrorCode =
|
||||||
|
## Checks ``osLastError`` for a valid error. If it has been reset it uses
|
||||||
|
## the last error stored in the socket object.
|
||||||
|
result = osLastError()
|
||||||
|
if result == 0.OSErrorCode:
|
||||||
|
result = socket.lastError
|
||||||
|
if result == 0.OSErrorCode:
|
||||||
|
raise newException(OSError, "No valid socket error code available")
|
||||||
|
|
||||||
proc socketError*(socket: Socket, err: int = -1, async = false,
|
proc socketError*(socket: Socket, err: int = -1, async = false,
|
||||||
lastError = (-1).OSErrorCode) =
|
lastError = (-1).OSErrorCode) =
|
||||||
## Raises an OSError based on the error code returned by ``SSLGetError``
|
## Raises an OSError based on the error code returned by ``SSLGetError``
|
||||||
|
|
@ -276,7 +286,7 @@ proc socketError*(socket: Socket, err: int = -1, async = false,
|
||||||
else: raiseSSLError("Unknown Error")
|
else: raiseSSLError("Unknown Error")
|
||||||
|
|
||||||
if err == -1 and not (when defined(ssl): socket.isSSL else: false):
|
if err == -1 and not (when defined(ssl): socket.isSSL else: false):
|
||||||
let lastE = if lastError.int == -1: osLastError() else: lastError
|
var lastE = if lastError.int == -1: getSocketError(socket) else: lastError
|
||||||
if async:
|
if async:
|
||||||
when useWinVersion:
|
when useWinVersion:
|
||||||
if lastE.int32 == WSAEWOULDBLOCK:
|
if lastE.int32 == WSAEWOULDBLOCK:
|
||||||
|
|
@ -569,6 +579,10 @@ proc readIntoBuf(socket: Socket, flags: int32): int =
|
||||||
result = recv(socket.fd, addr(socket.buffer), cint(socket.buffer.high), flags)
|
result = recv(socket.fd, addr(socket.buffer), cint(socket.buffer.high), flags)
|
||||||
else:
|
else:
|
||||||
result = recv(socket.fd, addr(socket.buffer), cint(socket.buffer.high), flags)
|
result = recv(socket.fd, addr(socket.buffer), cint(socket.buffer.high), flags)
|
||||||
|
if result < 0:
|
||||||
|
# Save it in case it gets reset (the Nim codegen occassionally may call
|
||||||
|
# Win API functions which reset it).
|
||||||
|
socket.lastError = osLastError()
|
||||||
if result <= 0:
|
if result <= 0:
|
||||||
socket.bufLen = 0
|
socket.bufLen = 0
|
||||||
socket.currPos = 0
|
socket.currPos = 0
|
||||||
|
|
@ -624,6 +638,9 @@ proc recv*(socket: Socket, data: pointer, size: int): int {.tags: [ReadIOEffect]
|
||||||
result = recv(socket.fd, data, size.cint, 0'i32)
|
result = recv(socket.fd, data, size.cint, 0'i32)
|
||||||
else:
|
else:
|
||||||
result = recv(socket.fd, data, size.cint, 0'i32)
|
result = recv(socket.fd, data, size.cint, 0'i32)
|
||||||
|
if result < 0:
|
||||||
|
# Save the error in case it gets reset.
|
||||||
|
socket.lastError = osLastError()
|
||||||
|
|
||||||
proc waitFor(socket: Socket, waited: var float, timeout, size: int,
|
proc waitFor(socket: Socket, waited: var float, timeout, size: int,
|
||||||
funcName: string): int {.tags: [TimeEffect].} =
|
funcName: string): int {.tags: [TimeEffect].} =
|
||||||
|
|
@ -696,7 +713,7 @@ proc recv*(socket: Socket, data: var string, size: int, timeout = -1,
|
||||||
result = recv(socket, cstring(data), size, timeout)
|
result = recv(socket, cstring(data), size, timeout)
|
||||||
if result < 0:
|
if result < 0:
|
||||||
data.setLen(0)
|
data.setLen(0)
|
||||||
let lastError = osLastError()
|
let lastError = getSocketError(socket)
|
||||||
if flags.isDisconnectionError(lastError): return
|
if flags.isDisconnectionError(lastError): return
|
||||||
socket.socketError(result, lastError = lastError)
|
socket.socketError(result, lastError = lastError)
|
||||||
data.setLen(result)
|
data.setLen(result)
|
||||||
|
|
@ -721,6 +738,7 @@ proc peekChar(socket: Socket, c: var char): int {.tags: [ReadIOEffect].} =
|
||||||
return
|
return
|
||||||
result = recv(socket.fd, addr(c), 1, MSG_PEEK)
|
result = recv(socket.fd, addr(c), 1, MSG_PEEK)
|
||||||
|
|
||||||
|
import winlean
|
||||||
proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
|
proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
|
||||||
flags = {SocketFlag.SafeDisconn}) {.
|
flags = {SocketFlag.SafeDisconn}) {.
|
||||||
tags: [ReadIOEffect, TimeEffect].} =
|
tags: [ReadIOEffect, TimeEffect].} =
|
||||||
|
|
@ -744,7 +762,7 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
|
||||||
line.add("\c\L")
|
line.add("\c\L")
|
||||||
|
|
||||||
template raiseSockError(): stmt {.dirty, immediate.} =
|
template raiseSockError(): stmt {.dirty, immediate.} =
|
||||||
let lastError = osLastError()
|
let lastError = getSocketError(socket)
|
||||||
if flags.isDisconnectionError(lastError): setLen(line.string, 0); return
|
if flags.isDisconnectionError(lastError): setLen(line.string, 0); return
|
||||||
socket.socketError(n, lastError = lastError)
|
socket.socketError(n, lastError = lastError)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue