This commit is contained in:
Araq 2015-03-16 22:39:48 +01:00
commit bc264618f5
4 changed files with 93 additions and 32 deletions

View file

@ -1335,8 +1335,12 @@ proc propagateToOwner*(owner, elem: PType) =
if elem.isMetaType:
owner.flags.incl tfHasMeta
if owner.kind != tyProc:
if elem.isGCedMem or tfHasGCedMem in elem.flags:
if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
tyGenericInvocation}:
let elemB = elem.skipTypes({tyGenericInst})
if elemB.isGCedMem or tfHasGCedMem in elemB.flags:
# for simplicity, we propagate this flag even to generics. We then
# ensure this doesn't bite us in sempass2.
owner.flags.incl tfHasGCedMem
proc rawAddSon*(father, son: PType) =

View file

@ -209,8 +209,7 @@ proc useVar(a: PEffects, n: PNode) =
a.init.add s.id
if {sfGlobal, sfThread} * s.flags == {sfGlobal} and s.kind in {skVar, skLet}:
if s.guard != nil: guardGlobal(a, n, s.guard)
if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and
tfGcSafe notin s.typ.flags:
if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem):
if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
markGcUnsafe(a)

View file

@ -0,0 +1,26 @@
# bug #2257
import threadpool
type StringChannel = TChannel[string]
var channels: array[1..3, StringChannel]
type
MyObject[T] = object
x: T
var global: MyObject[string]
var globalB: MyObject[float]
proc consumer(ix : int) {.thread.} =
echo channels[ix].recv() ###### not GC-safe: 'channels'
echo globalB
proc main =
for ix in 1..3: channels[ix].open()
for ix in 1..3: spawn consumer(ix)
for ix in 1..3: channels[ix].send("test")
sync()
for ix in 1..3: channels[ix].close()
when isMainModule:
main()

View file

@ -0,0 +1,32 @@
discard """
errormsg: "'consumer' is not GC-safe"
line: 19
"""
# bug #2257
import threadpool
type StringChannel = TChannel[string]
var channels: array[1..3, StringChannel]
type
MyObject[T] = object
x: T
var global: MyObject[string]
var globalB: MyObject[float]
proc consumer(ix : int) {.thread.} =
echo channels[ix].recv() ###### not GC-safe: 'channels'
echo global
echo globalB
proc main =
for ix in 1..3: channels[ix].open()
for ix in 1..3: spawn consumer(ix)
for ix in 1..3: channels[ix].send("test")
sync()
for ix in 1..3: channels[ix].close()
when isMainModule:
main()