More future debug info. Added new error code to SafeDisconn list.

This commit is contained in:
Dominik Picheta 2014-08-09 20:50:06 +01:00
commit 7358fc256f
4 changed files with 24 additions and 6 deletions

View file

@ -41,7 +41,8 @@ type
cb: proc () {.closure,gcsafe.} cb: proc () {.closure,gcsafe.}
finished: bool finished: bool
error*: ref EBase error*: ref EBase
when defined(debug): errorStackTrace*: string
when not defined(release):
stackTrace: string ## For debugging purposes only. stackTrace: string ## For debugging purposes only.
id: int id: int
fromProc: string fromProc: string
@ -57,14 +58,14 @@ proc newFuture*[T](fromProc: string = "unspecified"): PFuture[T] =
## that this future belongs to, is a good habit as it helps with debugging. ## that this future belongs to, is a good habit as it helps with debugging.
new(result) new(result)
result.finished = false result.finished = false
when defined(debug): when not defined(release):
result.stackTrace = getStackTrace() result.stackTrace = getStackTrace()
result.id = currentID result.id = currentID
result.fromProc = fromProc result.fromProc = fromProc
currentID.inc() currentID.inc()
proc checkFinished[T](future: PFuture[T]) = proc checkFinished[T](future: PFuture[T]) =
when defined(debug): when not defined(release):
if future.finished: if future.finished:
echo("<-----> ", future.id, " ", future.fromProc) echo("<-----> ", future.id, " ", future.fromProc)
echo(future.stackTrace) echo(future.stackTrace)
@ -101,6 +102,8 @@ proc fail*[T](future: PFuture[T], error: ref EBase) =
checkFinished(future) checkFinished(future)
future.finished = true future.finished = true
future.error = error future.error = error
future.errorStackTrace =
if getStackTrace(error) == "": getStackTrace() else: getStackTrace(error)
if future.cb != nil: if future.cb != nil:
future.cb() future.cb()
else: else:
@ -128,6 +131,15 @@ proc `callback=`*[T](future: PFuture[T],
## If future has already completed then ``cb`` will be called immediately. ## If future has already completed then ``cb`` will be called immediately.
future.callback = proc () = cb(future) future.callback = proc () = cb(future)
proc echoOriginalStackTrace[T](future: PFuture[T]) =
# TODO: Come up with something better.
when not defined(release):
echo("Original stack trace in ", future.fromProc, ":")
if not future.errorStackTrace.isNil() and future.errorStackTrace != "":
echo(future.errorStackTrace)
else:
echo("Empty or nil stack trace.")
proc read*[T](future: PFuture[T]): T = proc read*[T](future: PFuture[T]): T =
## Retrieves the value of ``future``. Future must be finished otherwise ## Retrieves the value of ``future``. Future must be finished otherwise
## this function will fail with a ``EInvalidValue`` exception. ## this function will fail with a ``EInvalidValue`` exception.
@ -135,6 +147,7 @@ proc read*[T](future: PFuture[T]): T =
## If the result of the future is an error then that error will be raised. ## If the result of the future is an error then that error will be raised.
if future.finished: if future.finished:
if future.error != nil: if future.error != nil:
echoOriginalStackTrace(future)
raise future.error raise future.error
when T isnot void: when T isnot void:
return future.value return future.value
@ -165,6 +178,7 @@ proc asyncCheck*[T](future: PFuture[T]) =
future.callback = future.callback =
proc () = proc () =
if future.failed: if future.failed:
echoOriginalStackTrace(future)
raise future.error raise future.error
type type
@ -438,7 +452,10 @@ when defined(windows) or defined(nimdoc):
copyMem(addr data[0], addr dataBuf.buf[0], bytesCount) copyMem(addr data[0], addr dataBuf.buf[0], bytesCount)
retFuture.complete($data) retFuture.complete($data)
else: else:
retFuture.fail(newException(EOS, osErrorMsg(errcode))) if flags.isDisconnectionError(errcode):
retFuture.complete("")
else:
retFuture.fail(newException(EOS, osErrorMsg(errcode)))
if dataBuf.buf != nil: if dataBuf.buf != nil:
dealloc dataBuf.buf dealloc dataBuf.buf
dataBuf.buf = nil dataBuf.buf = nil

View file

@ -361,7 +361,7 @@ proc isDisconnectionError*(flags: set[TSocketFlags],
when useWinVersion: when useWinVersion:
TSocketFlags.SafeDisconn in flags and TSocketFlags.SafeDisconn in flags and
lastError.int32 in {WSAECONNRESET, WSAECONNABORTED, WSAENETRESET, lastError.int32 in {WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
WSAEDISCON} WSAEDISCON, ERROR_NETNAME_DELETED}
else: else:
TSocketFlags.SafeDisconn in flags and TSocketFlags.SafeDisconn in flags and
lastError.int32 in {ECONNRESET, EPIPE, ENETRESET} lastError.int32 in {ECONNRESET, EPIPE, ENETRESET}

View file

@ -22,7 +22,7 @@ const useWinVersion = defined(Windows) or defined(nimdoc)
when useWinVersion: when useWinVersion:
import winlean import winlean
export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET, export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
WSAEDISCON WSAEDISCON, ERROR_NETNAME_DELETED
else: else:
import posix import posix
export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL, export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL,

View file

@ -664,6 +664,7 @@ const
WSAEDISCON* = 10101 WSAEDISCON* = 10101
WSAENETRESET* = 10052 WSAENETRESET* = 10052
WSAETIMEDOUT* = 10060 WSAETIMEDOUT* = 10060
ERROR_NETNAME_DELETED* = 64
proc CreateIoCompletionPort*(FileHandle: THANDLE, ExistingCompletionPort: THANDLE, proc CreateIoCompletionPort*(FileHandle: THANDLE, ExistingCompletionPort: THANDLE,
CompletionKey: DWORD, CompletionKey: DWORD,