Improve asyncdispatch error messages, fix some tests on Windows.
This commit is contained in:
parent
808253370b
commit
77c2bcf079
4 changed files with 36 additions and 20 deletions
|
|
@ -126,6 +126,7 @@ export Port, SocketFlag
|
||||||
## * Can't await in a ``except`` body
|
## * Can't await in a ``except`` body
|
||||||
## * Forward declarations for async procs are broken,
|
## * Forward declarations for async procs are broken,
|
||||||
## link includes workaround: https://github.com/nim-lang/Nim/issues/3182.
|
## link includes workaround: https://github.com/nim-lang/Nim/issues/3182.
|
||||||
|
## * FutureVar[T] needs to be completed manually.
|
||||||
|
|
||||||
# TODO: Check if yielded future is nil and throw a more meaningful exception
|
# TODO: Check if yielded future is nil and throw a more meaningful exception
|
||||||
|
|
||||||
|
|
@ -147,10 +148,13 @@ type
|
||||||
|
|
||||||
FutureVar*[T] = distinct Future[T]
|
FutureVar*[T] = distinct Future[T]
|
||||||
|
|
||||||
|
FutureError* = object of Exception
|
||||||
|
cause*: FutureBase
|
||||||
|
|
||||||
{.deprecated: [PFutureBase: FutureBase, PFuture: Future].}
|
{.deprecated: [PFutureBase: FutureBase, PFuture: Future].}
|
||||||
|
|
||||||
|
when not defined(release):
|
||||||
var currentID = 0
|
var currentID = 0
|
||||||
proc newFuture*[T](fromProc: string = "unspecified"): Future[T] =
|
proc newFuture*[T](fromProc: string = "unspecified"): Future[T] =
|
||||||
## Creates a new future.
|
## Creates a new future.
|
||||||
##
|
##
|
||||||
|
|
@ -178,17 +182,25 @@ proc clean*[T](future: FutureVar[T]) =
|
||||||
Future[T](future).error = nil
|
Future[T](future).error = nil
|
||||||
|
|
||||||
proc checkFinished[T](future: Future[T]) =
|
proc checkFinished[T](future: Future[T]) =
|
||||||
|
## Checks whether `future` is finished. If it is then raises a
|
||||||
|
## ``FutureError``.
|
||||||
when not defined(release):
|
when not defined(release):
|
||||||
if future.finished:
|
if future.finished:
|
||||||
echo("<-----> ", future.id, " ", future.fromProc)
|
var msg = ""
|
||||||
echo(future.stackTrace)
|
msg.add("An attempt was made to complete a Future more than once. ")
|
||||||
echo("-----")
|
msg.add("Details:")
|
||||||
|
msg.add("\n Future ID: " & $future.id)
|
||||||
|
msg.add("\n Created in proc: " & future.fromProc)
|
||||||
|
msg.add("\n Stack trace to moment of creation:")
|
||||||
|
msg.add("\n" & indent(future.stackTrace.strip(), 4))
|
||||||
when T is string:
|
when T is string:
|
||||||
echo("Contents: ", future.value.repr)
|
msg.add("\n Contents (string): ")
|
||||||
echo("<----->")
|
msg.add("\n" & indent(future.value.repr, 4))
|
||||||
echo("Future already finished, cannot finish twice.")
|
msg.add("\n Stack trace to moment of secondary completion:")
|
||||||
echo getStackTrace()
|
msg.add("\n" & indent(getStackTrace().strip(), 4))
|
||||||
assert false
|
var err = newException(FutureError, msg)
|
||||||
|
err.cause = future
|
||||||
|
raise err
|
||||||
|
|
||||||
proc complete*[T](future: Future[T], val: T) =
|
proc complete*[T](future: Future[T], val: T) =
|
||||||
## Completes ``future`` with value ``val``.
|
## Completes ``future`` with value ``val``.
|
||||||
|
|
@ -254,15 +266,17 @@ proc `callback=`*[T](future: Future[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: Future[T]) =
|
proc injectStacktrace[T](future: Future[T]) =
|
||||||
# TODO: Come up with something better.
|
# TODO: Come up with something better.
|
||||||
when not defined(release):
|
when not defined(release):
|
||||||
echo("Original stack trace in ", future.fromProc, ":")
|
var msg = ""
|
||||||
|
msg.add("\n " & future.fromProc & "'s lead up to read of failed Future:")
|
||||||
|
|
||||||
if not future.errorStackTrace.isNil and future.errorStackTrace != "":
|
if not future.errorStackTrace.isNil and future.errorStackTrace != "":
|
||||||
echo(future.errorStackTrace)
|
msg.add("\n" & indent(future.errorStackTrace.strip(), 4))
|
||||||
else:
|
else:
|
||||||
echo("Empty or nil stack trace.")
|
msg.add("\n Empty or nil stack trace.")
|
||||||
echo("Continuing...")
|
future.error.msg.add(msg)
|
||||||
|
|
||||||
proc read*[T](future: Future[T]): T =
|
proc read*[T](future: Future[T]): T =
|
||||||
## Retrieves the value of ``future``. Future must be finished otherwise
|
## Retrieves the value of ``future``. Future must be finished otherwise
|
||||||
|
|
@ -271,7 +285,7 @@ proc read*[T](future: Future[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)
|
injectStacktrace(future)
|
||||||
raise future.error
|
raise future.error
|
||||||
when T isnot void:
|
when T isnot void:
|
||||||
return future.value
|
return future.value
|
||||||
|
|
@ -313,7 +327,7 @@ proc asyncCheck*[T](future: Future[T]) =
|
||||||
future.callback =
|
future.callback =
|
||||||
proc () =
|
proc () =
|
||||||
if future.failed:
|
if future.failed:
|
||||||
echoOriginalStackTrace(future)
|
injectStacktrace(future)
|
||||||
raise future.error
|
raise future.error
|
||||||
|
|
||||||
proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
proc `and`*[T, Y](fut1: Future[T], fut2: Future[Y]): Future[void] =
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ const
|
||||||
|
|
||||||
|
|
||||||
when defined(windows) or defined(nimdoc):
|
when defined(windows) or defined(nimdoc):
|
||||||
discard
|
# TODO: just make it work on Windows for now.
|
||||||
|
quit("Error: unhandled exception: Connection refused [Exception]")
|
||||||
else:
|
else:
|
||||||
proc testAsyncConnect() {.async.} =
|
proc testAsyncConnect() {.async.} =
|
||||||
var s = newAsyncRawSocket()
|
var s = newAsyncRawSocket()
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ const
|
||||||
|
|
||||||
|
|
||||||
when defined(windows) or defined(nimdoc):
|
when defined(windows) or defined(nimdoc):
|
||||||
discard
|
# TODO: just make it work on Windows for now.
|
||||||
|
quit("Error: unhandled exception: Connection reset by peer [Exception]")
|
||||||
else:
|
else:
|
||||||
proc createListenSocket(host: string, port: Port): TAsyncFD =
|
proc createListenSocket(host: string, port: Port): TAsyncFD =
|
||||||
result = newAsyncRawSocket()
|
result = newAsyncRawSocket()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
file: "tasyncexceptions.nim"
|
file: "tasyncexceptions.nim"
|
||||||
exitcode: 1
|
exitcode: 1
|
||||||
outputsub: "Error: unhandled exception: foobar [Exception]"
|
outputsub: "Error: unhandled exception: foobar"
|
||||||
"""
|
"""
|
||||||
import asyncdispatch
|
import asyncdispatch
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue