diff --git a/lib/pure/asyncfutures.nim b/lib/pure/asyncfutures.nim index d8385a9cb..f75859e4c 100644 --- a/lib/pure/asyncfutures.nim +++ b/lib/pure/asyncfutures.nim @@ -217,6 +217,20 @@ proc `callback=`*[T](future: Future[T], ## If future has already completed then ``cb`` will be called immediately. future.callback = proc () = cb(future) +proc diff[T](a, b: seq[T]): (int, seq[T]) = + ## Iterates through both sequences until the items do not match, + ## returns the remainder of `b` after the last item that does not match + ## together with the index of the last match. + ## + ## .. code-block::nim + ## doAssert(diff(@[1,2,42,123], @[1,2,123,678,21]) == (1, @[123,678,21])) + var lastIndex = 0 + for i in 0 .. = entries.len: @@ -230,8 +244,21 @@ proc processEntries(entries: seq[StackTraceEntry]): seq[StackTraceEntry] = var entry = entries[i] if entry.procName.isNil: - # Start of a re-raise traceback which we do not care for. - break + # Start of a re-raise traceback which may contain more info. + # Find where the re-raised traceback ends. + assert entry.line == -10 # Signifies start of re-raise block. + var reRaiseEnd = i+1 + while reRaiseEnd < entries.len and not entries[reRaiseEnd].procName.isNil: + reRaiseEnd.inc() + assert entries[reRaiseEnd].procName.isNil + assert entries[reRaiseEnd].line == -100 # Signifies end of re-raise block. + let reRaisedEntries = processEntries(entries[i+1 .. reRaiseEnd-1]) + + let (lastIndex, remainder) = diff(result, reRaisedEntries) + for i in 0.. 0: - future.error.msg.add(indent & "└─" & hint & "\n") + newMsg.add(indent & "└─" & hint & "\n") - future.error.msg.add("Exception message: " & originalMsg & "\n") - future.error.msg.add("Exception type: ") + newMsg.add("Exception message: " & exceptionMsg & "\n") + newMsg.add("Exception type:") # # For debugging purposes # for entry in getStackTraceEntries(future.error): - # future.error.msg.add "\n" & $entry + # newMsg.add "\n" & $entry + future.error.msg = newMsg proc read*[T](future: Future[T] | FutureVar[T]): T = ## Retrieves the value of ``future``. Future must be finished otherwise diff --git a/tests/async/tasync_traceback.nim b/tests/async/tasync_traceback.nim index c69721f39..6ab7ef915 100644 --- a/tests/async/tasync_traceback.nim +++ b/tests/async/tasync_traceback.nim @@ -3,10 +3,36 @@ discard """ output: ''' b failure Async traceback: - tasync_traceback.nim(49) tasync_traceback - tasync_traceback.nim(47) a - tasync_traceback.nim(44) b + tasync_traceback.nim(75) tasync_traceback + asyncmacro.nim(393) a + asyncmacro.nim(43) cb0 + └─Resumes an async procedure + asyncfutures.nim(211) callback= + asyncfutures.nim(190) addCallback + asyncfutures.nim(53) callSoon + asyncmacro.nim(34) cb0 + └─Resumes an async procedure + asyncmacro.nim(0) aIter + asyncfutures.nim(355) read + tasync_traceback.nim(73) a + tasync_traceback.nim(70) b Exception message: b failure +Exception type: + +bar failure +Async traceback: + tasync_traceback.nim(91) tasync_traceback + asyncdispatch.nim(1204) waitFor + asyncdispatch.nim(1253) poll + └─Processes asynchronous completion events + asyncdispatch.nim(181) processPendingCallbacks + └─Executes pending callbacks + asyncmacro.nim(34) cb0 + └─Resumes an async procedure + asyncmacro.nim(0) fooIter + asyncfutures.nim(355) read + tasync_traceback.nim(86) barIter +Exception message: bar failure Exception type:''' """ import asyncdispatch @@ -51,3 +77,18 @@ try: discard waitFor aFut except Exception as exc: echo exc.msg +echo() + +# From #6803 +proc bar(): Future[string] {.async.} = + await sleepAsync(100) + if true: + raise newException(OSError, "bar failure") + +proc foo(): Future[string] {.async.} = return await bar() + +try: + echo waitFor(foo()) +except Exception as exc: + echo exc.msg +echo() \ No newline at end of file