* fixes #13881
* documented changed requirements for system.onThreadDestruction
* destructors.rst: update the documentation
This commit is contained in:
Andreas Rumpf 2020-05-12 15:46:24 +02:00 • committed by GitHub
commit 06dfd31612
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 84 additions and 23 deletions

View file

@ -493,6 +493,14 @@ proc reraiseException() {.compilerRtl.} =
else:
raiseExceptionAux(currException)
proc threadTrouble() =
# also forward declared, it is 'raises: []' hence the try-except.
try:
if currException != nil: reportUnhandledError(currException)
except:
discard
quit 1
proc writeStackTrace() =
when hasSomeStackTrace:
var s = ""

View file

@ -843,9 +843,10 @@ when not defined(useNimRtl):
proc GC_disable() =
inc(gch.recGcLock)
proc GC_enable() =
if gch.recGcLock <= 0:
raise newException(AssertionDefect,
"API usage error: GC_enable called but GC is already enabled")
when defined(nimDoesntTrackDefects):
if gch.recGcLock <= 0:
raise newException(AssertionDefect,
"API usage error: GC_enable called but GC is already enabled")
dec(gch.recGcLock)
proc GC_setStrategy(strategy: GC_Strategy) =

View file

@ -14,7 +14,7 @@ when hasAlloc:
gcOptimizeSpace ## optimize for memory footprint
when hasAlloc and not defined(js) and not usesDestructors:
proc GC_disable*() {.rtl, inl, benign.}
proc GC_disable*() {.rtl, inl, benign, raises: [].}
## Disables the GC. If called `n` times, `n` calls to `GC_enable`
## are needed to reactivate the GC.
##
@ -22,7 +22,7 @@ when hasAlloc and not defined(js) and not usesDestructors:
## the mark and sweep phase with
## `GC_disableMarkAndSweep <#GC_disableMarkAndSweep>`_.
proc GC_enable*() {.rtl, inl, benign.}
proc GC_enable*() {.rtl, inl, benign, raises: [].}
## Enables the GC again.
proc GC_fullCollect*() {.rtl, benign.}
@ -54,7 +54,7 @@ when hasAlloc and not defined(js) and not usesDestructors:
proc GC_unref*(x: string) {.magic: "GCunref", benign.}
## See the documentation of `GC_ref <#GC_ref,string>`_.
proc nimGC_setStackBottom*(theStackBottom: pointer) {.compilerRtl, noinline, benign.}
proc nimGC_setStackBottom*(theStackBottom: pointer) {.compilerRtl, noinline, benign, raises: [].}
## Expands operating GC stack range to `theStackBottom`. Does nothing
## if current stack bottom is already lower than `theStackBottom`.

View file

@ -495,9 +495,10 @@ when not defined(useNimRtl):
proc GC_disable() =
inc(gch.recGcLock)
proc GC_enable() =
if gch.recGcLock <= 0:
raise newException(AssertionDefect,
"API usage error: GC_enable called but GC is already enabled")
when defined(nimDoesntTrackDefects):
if gch.recGcLock <= 0:
raise newException(AssertionDefect,
"API usage error: GC_enable called but GC is already enabled")
dec(gch.recGcLock)
proc GC_setStrategy(strategy: GC_Strategy) = discard

View file

@ -89,9 +89,9 @@ type
data: TArg
var
threadDestructionHandlers {.rtlThreadVar.}: seq[proc () {.closure, gcsafe.}]
threadDestructionHandlers {.rtlThreadVar.}: seq[proc () {.closure, gcsafe, raises: [].}]
proc onThreadDestruction*(handler: proc () {.closure, gcsafe.}) =
proc onThreadDestruction*(handler: proc () {.closure, gcsafe, raises: [].}) =
## Registers a *thread local* handler that is called at the thread's
## destruction.
##
@ -105,7 +105,10 @@ template afterThreadRuns() =
threadDestructionHandlers[i]()
when not defined(boehmgc) and not hasSharedHeap and not defined(gogc) and not defined(gcRegions):
proc deallocOsPages() {.rtl.}
proc deallocOsPages() {.rtl, raises: [].}
proc threadTrouble() {.raises: [].}
## defined in system/excpt.nim
when defined(boehmgc):
type GCStackBaseProc = proc(sb: pointer, t: pointer) {.noconv.}
@ -116,7 +119,7 @@ when defined(boehmgc):
proc boehmGC_unregister_my_thread()
{.importc: "GC_unregister_my_thread", boehmGC.}
proc threadProcWrapDispatch[TArg](sb: pointer, thrd: pointer) {.noconv.} =
proc threadProcWrapDispatch[TArg](sb: pointer, thrd: pointer) {.noconv, raises: [].} =
boehmGC_register_my_thread(sb)
try:
let thrd = cast[ptr Thread[TArg]](thrd)
@ -124,11 +127,13 @@ when defined(boehmgc):
thrd.dataFn()
else:
thrd.dataFn(thrd.data)
except:
threadTrouble()
finally:
afterThreadRuns()
boehmGC_unregister_my_thread()
else:
proc threadProcWrapDispatch[TArg](thrd: ptr Thread[TArg]) =
proc threadProcWrapDispatch[TArg](thrd: ptr Thread[TArg]) {.raises: [].} =
try:
when TArg is void:
thrd.dataFn()
@ -139,21 +144,22 @@ else:
var x: TArg
deepCopy(x, thrd.data)
thrd.dataFn(x)
except:
threadTrouble()
finally:
afterThreadRuns()
proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) {.raises: [].} =
when defined(boehmgc):
boehmGC_call_with_stack_base(threadProcWrapDispatch[TArg], thrd)
elif not defined(nogc) and not defined(gogc) and not defined(gcRegions) and not usesDestructors:
var p {.volatile.}: proc(a: ptr Thread[TArg]) {.nimcall, gcsafe.} =
threadProcWrapDispatch[TArg]
var p {.volatile.}: pointer
# init the GC for refc/markandsweep
nimGC_setStackBottom(addr(p))
initGC()
when declared(threadType):
threadType = ThreadType.NimThread
p(thrd)
threadProcWrapDispatch[TArg](thrd)
when declared(deallocOsPages): deallocOsPages()
else:
threadProcWrapDispatch(thrd)