diff options
author | yatsen1 <kitech@sixlan.tk> | 2020-09-18 23:17:09 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-18 17:17:09 +0200 |
commit | 341cd844b282cc6ed3b1fc4c1ef10c38fc06d5e7 (patch) | |
tree | 151533e9e12bd39f9302a3019983c8f603e182c7 /lib/pure/coro.nim | |
parent | d19316bbb986a7dd1d6d091173963f6e74c65991 (diff) | |
download | Nim-341cd844b282cc6ed3b1fc4c1ef10c38fc06d5e7.tar.gz |
fix coro proc crash for stack problem when run long enough than a GC cycle (#7612) (#11410)
Co-authored-by: drswinghead <drswinghead@gmail.com> Co-authored-by: Clyybber <darkmine956@gmail.com>
Diffstat (limited to 'lib/pure/coro.nim')
-rw-r--r-- | lib/pure/coro.nim | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/lib/pure/coro.nim b/lib/pure/coro.nim index 6e49b6323..2a702b65b 100644 --- a/lib/pure/coro.nim +++ b/lib/pure/coro.nim @@ -36,6 +36,7 @@ const defaultStackSize = 512 * 1024 proc GC_addStack(bottom: pointer) {.cdecl, importc.} proc GC_removeStack(bottom: pointer) {.cdecl, importc.} proc GC_setActiveStack(bottom: pointer) {.cdecl, importc.} +proc GC_getActiveStack() : pointer {.cdecl, importc.} const CORO_BACKEND_UCONTEXT = 0 @@ -166,6 +167,7 @@ type coroutines: DoublyLinkedList[CoroutinePtr] current: DoublyLinkedNode[CoroutinePtr] loop: Coroutine + ncbottom: pointer # non coroutine stack botttom var ctx {.threadvar.}: CoroutineLoopContext @@ -183,6 +185,7 @@ proc initialize() = ctx.coroutines = initDoublyLinkedList[CoroutinePtr]() ctx.loop = Coroutine() ctx.loop.state = CORO_EXECUTING + ctx.ncbottom = GC_getActiveStack() when coroBackend == CORO_BACKEND_FIBERS: ctx.loop.execContext = ConvertThreadToFiberEx(nil, FIBER_FLAG_FLOAT_SWITCH) @@ -193,6 +196,7 @@ proc switchTo(current, to: CoroutinePtr) = to.lastRun = getTicks() # Update position of current stack so gc invoked from another stack knows how much to scan. GC_setActiveStack(current.stack.bottom) + nimGC_setStackBottom(current.stack.bottom) var frame = getFrameState() block: # Execution will switch to another fiber now. We do not need to update current stack @@ -215,12 +219,14 @@ proc switchTo(current, to: CoroutinePtr) = # Execution was just resumed. Restore frame information and set active stack. setFrameState(frame) GC_setActiveStack(current.stack.bottom) + nimGC_setStackBottom(ctx.ncbottom) proc suspend*(sleepTime: float = 0) = ## Stops coroutine execution and resumes no sooner than after ``sleeptime`` seconds. ## Until then other coroutines are executed. var current = getCurrent() current.sleepTime = sleepTime + nimGC_setStackBottom(ctx.ncbottom) switchTo(current, addr(ctx.loop)) proc runCurrentTask() = @@ -230,6 +236,7 @@ proc runCurrentTask() = block: var current = getCurrent() current.stack.bottom = sp + nimGC_setStackBottom(current.stack.bottom) # Execution of new fiber just started. Since it was entered not through `switchTo` we # have to set active stack here as well. GC_removeStack() has to be called in main loop # because we still need stack available in final suspend(0) call from which we will not @@ -244,6 +251,7 @@ proc runCurrentTask() = echo "Unhandled exception in coroutine." writeStackTrace() current.state = CORO_FINISHED + nimGC_setStackBottom(ctx.ncbottom) suspend(0) # Exit coroutine without returning from coroExecWithStack() doAssert false |