mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
Ensure channels don't leak exception effects (#25318)
The forward declarations cause `Exception` to be inferred - also, `llrecv` is an internal implementation detail and the type of the received item is controlled by generics, thus the ValueError raised there seems out of place for the generic api.
This commit is contained in:
@@ -118,21 +118,21 @@ when not defined(js):
|
||||
template `rawType=`(x: var Any, p: PNimType) =
|
||||
x.rawTypePtr = cast[pointer](p)
|
||||
|
||||
proc genericAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
|
||||
proc genericAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc, raises: [].}
|
||||
|
||||
when not defined(gcDestructors):
|
||||
proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
|
||||
proc incrSeq(seq: PGenSeq, elemSize, elemAlign: int): PGenSeq {.importCompilerProc.}
|
||||
proc newObj(typ: PNimType, size: int): pointer {.importCompilerProc.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.importCompilerProc.}
|
||||
proc objectInit(dest: pointer, typ: PNimType) {.importCompilerProc.}
|
||||
proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc, raises: [].}
|
||||
proc incrSeq(seq: PGenSeq, elemSize, elemAlign: int): PGenSeq {.importCompilerProc, raises: [].}
|
||||
proc newObj(typ: PNimType, size: int): pointer {.importCompilerProc, raises: [].}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.importCompilerProc, raises: [].}
|
||||
proc objectInit(dest: pointer, typ: PNimType) {.importCompilerProc, raises: [].}
|
||||
else:
|
||||
proc nimNewObj(size, align: int): pointer {.importCompilerProc.}
|
||||
proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.importCompilerProc.}
|
||||
proc nimNewObj(size, align: int): pointer {.importCompilerProc, raises: [].}
|
||||
proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.importCompilerProc, raises: [].}
|
||||
proc prepareSeqAddUninit(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
|
||||
importCompilerProc.}
|
||||
importCompilerProc, raises: [].}
|
||||
proc zeroNewElements(len: int; p: pointer; addlen, elemSize, elemAlign: int) {.
|
||||
importCompilerProc.}
|
||||
importCompilerProc, raises: [].}
|
||||
|
||||
include system/ptrarith
|
||||
|
||||
|
||||
@@ -138,6 +138,8 @@
|
||||
## localChannelExample() # "Hello from the main thread!"
|
||||
## ```
|
||||
|
||||
{.push raises: [], gcsafe.}
|
||||
|
||||
when not declared(ThisIsSystem):
|
||||
{.error: "You must not import this module explicitly".}
|
||||
|
||||
@@ -390,7 +392,7 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
|
||||
q.ready = false
|
||||
if typ != q.elemType:
|
||||
releaseSys(q.lock)
|
||||
raise newException(ValueError, "cannot receive message of wrong type")
|
||||
raiseAssert "cannot receive message of wrong type"
|
||||
rawRecv(q, res, typ)
|
||||
if q.maxItems > 0 and q.count == q.maxItems - 1:
|
||||
# Parent thread is awaiting in send. Wake it up.
|
||||
@@ -455,3 +457,5 @@ proc ready*[TMsg](c: var Channel[TMsg]): bool =
|
||||
## new messages.
|
||||
var q = cast[PRawChannel](addr(c))
|
||||
result = q.ready
|
||||
|
||||
{.pop.}
|
||||
@@ -97,7 +97,7 @@ type
|
||||
waZctDecRef, waPush
|
||||
#, waDebug
|
||||
|
||||
Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign, raises: [].}
|
||||
Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign, raises: [], gcsafe.}
|
||||
# A ref type can have a finalizer that is called before the object's
|
||||
# storage is freed.
|
||||
|
||||
@@ -481,17 +481,17 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
|
||||
{.pop.} # .stackTrace off
|
||||
{.pop.} # .profiler off
|
||||
|
||||
proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||
proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl, raises: [].} =
|
||||
result = rawNewObj(typ, size, gch)
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl, noinline.} =
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl, noinline, raises: [].} =
|
||||
result = rawNewObj(typ, size, gch)
|
||||
zeroMem(result, size)
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
|
||||
{.push overflowChecks: on.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl, raises: [].} =
|
||||
# `newObj` already uses locks, so no need for them here.
|
||||
let size = align(GenericSeqSize, typ.base.align) + len * typ.base.size
|
||||
result = newObj(typ, size)
|
||||
@@ -500,7 +500,7 @@ proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
{.pop.}
|
||||
|
||||
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl, noinline.} =
|
||||
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl, noinline, raises: [].} =
|
||||
# generates a new object and sets its reference counter to 1
|
||||
incTypeSize typ, size
|
||||
sysAssert(allocInv(gch.region), "newObjRC1 begin")
|
||||
@@ -528,7 +528,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl, noinline.} =
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
|
||||
{.push overflowChecks: on.}
|
||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl, raises: [].} =
|
||||
let size = align(GenericSeqSize, typ.base.align) + len * typ.base.size
|
||||
result = newObjRC1(typ, size)
|
||||
cast[PGenericSeq](result).len = len
|
||||
@@ -670,7 +670,7 @@ proc doOperation(p: pointer, op: WalkOp) =
|
||||
add(gch.tempStack, c)
|
||||
#of waDebug: debugGraph(c)
|
||||
|
||||
proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} =
|
||||
proc nimGCvisit(d: pointer, op: int) {.compilerRtl, raises: [].} =
|
||||
doOperation(d, WalkOp(op))
|
||||
|
||||
proc collectZCT(gch: var GcHeap): bool {.benign, raises: [].}
|
||||
|
||||
@@ -46,8 +46,8 @@ var
|
||||
newObjHook*: proc (typ: PNimType, size: int): pointer {.nimcall, tags: [], raises: [], gcsafe.}
|
||||
traverseObjHook*: proc (p: pointer, op: int) {.nimcall, tags: [], raises: [], gcsafe.}
|
||||
|
||||
proc nimGCvisit(p: pointer, op: int) {.inl, compilerRtl.} =
|
||||
proc nimGCvisit(p: pointer, op: int) {.inl, compilerRtl, raises: [].} =
|
||||
traverseObjHook(p, op)
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer {.inl, compilerRtl.} =
|
||||
proc newObj(typ: PNimType, size: int): pointer {.inl, compilerRtl, raises: [].} =
|
||||
result = newObjHook(typ, size)
|
||||
|
||||
@@ -36,7 +36,7 @@ type
|
||||
# local
|
||||
waMarkPrecise # fast precise marking
|
||||
|
||||
Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign, raises: [].}
|
||||
Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign, raises: [], gcsafe.}
|
||||
# A ref type can have a finalizer that is called before the object's
|
||||
# storage is freed.
|
||||
|
||||
@@ -289,23 +289,23 @@ when useCellIds:
|
||||
|
||||
{.pop.}
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl, raises: [].} =
|
||||
result = rawNewObj(typ, size, gch)
|
||||
zeroMem(result, size)
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
|
||||
proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||
proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl, raises: [].} =
|
||||
result = rawNewObj(typ, size, gch)
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
|
||||
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl, raises: [].} =
|
||||
result = rawNewObj(typ, size, gch)
|
||||
zeroMem(result, size)
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
|
||||
when not defined(nimSeqsV2):
|
||||
{.push overflowChecks: on.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl, raises: [].} =
|
||||
# `newObj` already uses locks, so no need for them here.
|
||||
let size = align(GenericSeqSize, typ.base.align) + len * typ.base.size
|
||||
result = newObj(typ, size)
|
||||
@@ -313,7 +313,7 @@ when not defined(nimSeqsV2):
|
||||
cast[PGenericSeq](result).reserved = len
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
|
||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl, raises: [].} =
|
||||
let size = align(GenericSeqSize, typ.base.align) + len * typ.base.size
|
||||
result = newObj(typ, size)
|
||||
cast[PGenericSeq](result).len = len
|
||||
@@ -346,7 +346,7 @@ when not defined(nimSeqsV2):
|
||||
result = cellToUsr(res)
|
||||
when defined(memProfiler): nimProfile(newsize-oldsize)
|
||||
|
||||
proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
|
||||
proc growObj(old: pointer, newsize: int): pointer {.rtl, raises: [].} =
|
||||
result = growObj(old, newsize, gch)
|
||||
|
||||
{.push profiler:off.}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
{.push raises: [], gcsafe.}
|
||||
|
||||
# "Stack GC" for embedded devices or ultra performance requirements.
|
||||
import std/private/syslocks
|
||||
|
||||
@@ -39,7 +41,7 @@ else:
|
||||
# We also support 'finalizers'.
|
||||
|
||||
type
|
||||
Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
|
||||
Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign, raises: [], gcsafe.}
|
||||
# A ref type can have a finalizer that is called before the object's
|
||||
# storage is freed.
|
||||
|
||||
@@ -305,26 +307,26 @@ proc rawNewSeq(r: var MemRegion, typ: PNimType, size: int): pointer =
|
||||
res.region = addr(r)
|
||||
result = res +! sizeof(SeqHeader)
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl, raises: [].} =
|
||||
sysAssert typ.kind notin {tySequence, tyString}, "newObj cannot be used to construct seqs"
|
||||
result = rawNewObj(tlRegion, typ, size)
|
||||
zeroMem(result, size)
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
|
||||
proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||
proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl, raises: [].} =
|
||||
sysAssert typ.kind notin {tySequence, tyString}, "newObj cannot be used to construct seqs"
|
||||
result = rawNewObj(tlRegion, typ, size)
|
||||
when defined(memProfiler): nimProfile(size)
|
||||
|
||||
{.push overflowChecks: on.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl, raises: [].} =
|
||||
let size = roundup(align(GenericSeqSize, typ.base.align) + len * typ.base.size, MemAlign)
|
||||
result = rawNewSeq(tlRegion, typ, size)
|
||||
zeroMem(result, size)
|
||||
cast[PGenericSeq](result).len = len
|
||||
cast[PGenericSeq](result).reserved = len
|
||||
|
||||
proc newStr(typ: PNimType, len: int; init: bool): pointer {.compilerRtl.} =
|
||||
proc newStr(typ: PNimType, len: int; init: bool): pointer {.compilerRtl, raises: [].} =
|
||||
let size = roundup(len + GenericSeqSize, MemAlign)
|
||||
result = rawNewSeq(tlRegion, typ, size)
|
||||
if init: zeroMem(result, size)
|
||||
@@ -332,14 +334,14 @@ proc newStr(typ: PNimType, len: int; init: bool): pointer {.compilerRtl.} =
|
||||
cast[PGenericSeq](result).reserved = len
|
||||
{.pop.}
|
||||
|
||||
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl, raises: [].} =
|
||||
result = rawNewObj(tlRegion, typ, size)
|
||||
zeroMem(result, size)
|
||||
|
||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
|
||||
proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl, raises: [].} =
|
||||
result = newSeq(typ, len)
|
||||
|
||||
proc growObj(regionUnused: var MemRegion; old: pointer, newsize: int): pointer =
|
||||
proc growObj(regionUnused: var MemRegion; old: pointer, newsize: int): pointer {.raises: [].} =
|
||||
let sh = cast[ptr SeqHeader](old -! sizeof(SeqHeader))
|
||||
let typ = sh.typ
|
||||
result = rawNewSeq(sh.region[], typ,
|
||||
@@ -351,7 +353,7 @@ proc growObj(regionUnused: var MemRegion; old: pointer, newsize: int): pointer =
|
||||
copyMem(result, old, oldsize)
|
||||
dealloc(sh.region[], old, roundup(oldsize, MemAlign))
|
||||
|
||||
proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
|
||||
proc growObj(old: pointer, newsize: int): pointer {.rtl, raises: [].} =
|
||||
result = growObj(tlRegion, old, newsize)
|
||||
|
||||
proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
|
||||
@@ -434,3 +436,5 @@ proc nimGC_setStackBottom(theStackBottom: pointer) = discard
|
||||
|
||||
proc nimGCref(x: pointer) {.compilerproc.} = discard
|
||||
proc nimGCunref(x: pointer) {.compilerproc.} = discard
|
||||
|
||||
{.pop.}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
{.push raises: [], gcsafe.}
|
||||
|
||||
|
||||
proc boehmGCinit {.importc: "GC_init", boehmGC.}
|
||||
@@ -95,7 +95,7 @@ proc initGC() =
|
||||
when hasThreadSupport:
|
||||
boehmGC_allow_register_threads()
|
||||
|
||||
proc boehmgc_finalizer(obj: pointer, typedFinalizer: (proc(x: pointer) {.cdecl.})) =
|
||||
proc boehmgc_finalizer(obj: pointer, typedFinalizer: (proc(x: pointer) {.cdecl, raises: [], gcsafe.})) =
|
||||
typedFinalizer(obj)
|
||||
|
||||
|
||||
@@ -138,3 +138,5 @@ proc deallocOsPages(r: var MemRegion) {.inline.} = discard
|
||||
proc deallocOsPages() {.inline.} = discard
|
||||
|
||||
include "system/cellsets"
|
||||
|
||||
{.pop.}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{.push raises: [], gcsafe.}
|
||||
|
||||
when defined(windows):
|
||||
const goLib = "libgo.dll"
|
||||
@@ -151,3 +152,5 @@ proc alloc0(r: var MemRegion, size: int): pointer =
|
||||
proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
|
||||
proc deallocOsPages(r: var MemRegion) {.inline.} = discard
|
||||
proc deallocOsPages() {.inline.} = discard
|
||||
|
||||
{.pop.}
|
||||
|
||||
@@ -20,7 +20,7 @@ proc newObjNoInit(typ: PNimType, size: int): pointer =
|
||||
result = alloc(size)
|
||||
|
||||
{.push overflowChecks: on.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc, raises: [].} =
|
||||
result = newObj(typ, align(GenericSeqSize, typ.align) + len * typ.base.size)
|
||||
cast[PGenericSeq](result).len = len
|
||||
cast[PGenericSeq](result).reserved = len
|
||||
|
||||
@@ -60,10 +60,10 @@ elif (defined(nogc) or defined(gcDestructors)) and defined(useMalloc):
|
||||
|
||||
when defined(nogc):
|
||||
proc GC_getStatistics(): string = ""
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerproc, raises: [].} =
|
||||
result = alloc0(size)
|
||||
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc, raises: [].} =
|
||||
result = newObj(typ, align(GenericSeqSize, typ.align) + len * typ.base.size)
|
||||
cast[PGenericSeq](result).len = len
|
||||
cast[PGenericSeq](result).reserved = len
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
{.push raises: [], gcsafe.}
|
||||
|
||||
proc roundup(x, v: int): int {.inline.} =
|
||||
result = (x + (v-1)) and not (v-1)
|
||||
sysAssert(result >= x, "roundup: result < x")
|
||||
@@ -216,3 +218,5 @@ elif hostOS == "standalone" or defined(StandaloneHeapSize):
|
||||
|
||||
else:
|
||||
{.error: "Port memory manager to your platform".}
|
||||
|
||||
{.pop.}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
# we don't use refcounts because that's a behaviour
|
||||
# the programmer may not want
|
||||
|
||||
{.push raises: [], gcsafe.}
|
||||
|
||||
proc dataPointer(a: PGenericSeq, elemAlign: int): pointer =
|
||||
cast[pointer](cast[int](a) +% align(GenericSeqSize, elemAlign))
|
||||
@@ -103,7 +104,7 @@ proc toNimStr(str: cstring, len: int): NimString {.compilerproc.} =
|
||||
copyMem(addr(result.data), str, len)
|
||||
result.data[len] = '\0'
|
||||
|
||||
proc toOwnedCopy(src: NimString): NimString {.inline.} =
|
||||
proc toOwnedCopy(src: NimString): NimString {.inline, raises: [].} =
|
||||
## Expects `src` to be not nil and initialized (len and terminating zero set)
|
||||
result = rawNewStringNoInit(src.len)
|
||||
result.len = src.len
|
||||
@@ -149,7 +150,7 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
|
||||
if (src.reserved and strlitFlag) != 0:
|
||||
result.reserved = (result.reserved and not strlitFlag) or seqShallowFlag
|
||||
|
||||
proc copyDeepString(src: NimString): NimString {.inline.} =
|
||||
proc copyDeepString(src: NimString): NimString {.inline, raises: [].} =
|
||||
if src != nil:
|
||||
result = toOwnedCopy(src)
|
||||
|
||||
@@ -358,3 +359,4 @@ func capacity*[T](self: seq[T]): int {.inline.} =
|
||||
let sek = cast[PGenericSeq](self)
|
||||
result = if sek != nil: sek.space else: 0
|
||||
|
||||
{.pop.}
|
||||
|
||||
@@ -12,14 +12,14 @@ var
|
||||
chan1.open()
|
||||
chan2.open()
|
||||
|
||||
proc routeMessage*(msg: BackendMessage) =
|
||||
proc routeMessage*(msg: BackendMessage) {.raises: [], gcsafe.} = # no exceptions!
|
||||
discard chan2.trySend(msg)
|
||||
|
||||
var
|
||||
recv: Thread[void]
|
||||
stopToken: Atomic[bool]
|
||||
|
||||
proc recvMsg() =
|
||||
proc recvMsg() {.raises: [], gcsafe.} = # no exceptions!
|
||||
while not stopToken.load(moRelaxed):
|
||||
let resp = chan1.tryRecv()
|
||||
if resp.dataAvailable:
|
||||
|
||||
Reference in New Issue
Block a user