diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2021-07-13 14:17:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-13 14:17:59 +0200 |
commit | 12da32a891b08f34acbb676001f0c211ecfe1af8 (patch) | |
tree | 196758792d748076c4958319dafb637c7681f53b | |
parent | b3aca78e228feb93d5dcd6f00cdd81e4178c24cc (diff) | |
download | Nim-12da32a891b08f34acbb676001f0c211ecfe1af8.tar.gz |
fixes #17893 (#18485)
* fixes #17893
-rw-r--r-- | compiler/liftdestructors.nim | 7 | ||||
-rw-r--r-- | tests/arc/tshared_ptr_crash.nim | 67 |
2 files changed, 68 insertions, 6 deletions
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index b2b70edee..cc7e36cdb 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -416,12 +416,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = body.add destructorCall(c, op, x) result = true #result = addDestructorCall(c, t, body, x) - of attachedAsgn, attachedSink: - var op = getAttachedOp(c.g, t, c.kind) - result = considerAsgnOrSink(c, t, body, x, y, op) - if op != nil: - setAttachedOp(c.g, c.idgen.module, t, c.kind, op) - of attachedTrace: + of attachedAsgn, attachedSink, attachedTrace: var op = getAttachedOp(c.g, t, c.kind) if op != nil and sfOverriden in op.flags: if op.ast.isGenericRoutine: diff --git a/tests/arc/tshared_ptr_crash.nim b/tests/arc/tshared_ptr_crash.nim new file mode 100644 index 000000000..1794834db --- /dev/null +++ b/tests/arc/tshared_ptr_crash.nim @@ -0,0 +1,67 @@ +discard """ + cmd: "nim c --threads:on --gc:arc $file" + action: compile +""" + +# bug #17893 + +type + SharedPtr*[T] = object + val: ptr tuple[value: T, atomicCounter: int] + +proc `=destroy`*[T](p: var SharedPtr[T]) = + mixin `=destroy` + if p.val != nil: + if atomicLoadN(addr p.val[].atomicCounter, AtomicConsume) == 0: + `=destroy`(p.val[]) + deallocShared(p.val) + else: + discard atomicDec(p.val[].atomicCounter) + +proc `=copy`*[T](dest: var SharedPtr[T], src: SharedPtr[T]) = + if src.val != nil: + discard atomicInc(src.val[].atomicCounter) + if dest.val != nil: + `=destroy`(dest) + dest.val = src.val + +proc newSharedPtr*[T](val: sink T): SharedPtr[T] {.nodestroy.} = + result.val = cast[typeof(result.val)](allocShared(sizeof(result.val[]))) + result.val.atomicCounter = 0 + result.val.value = val + +proc isNil*[T](p: SharedPtr[T]): bool {.inline.} = + p.val == nil + +proc `[]`*[T](p: SharedPtr[T]): var T {.inline.} = + when compileOption("boundChecks"): + doAssert(p.val != nil, "deferencing nil shared pointer") + result = p.val.value + +type + Sender*[T] = object + queue: SharedPtr[seq[T]] + +proc newSender*[T](queue: sink SharedPtr[seq[T]]): Sender[T] = + result = Sender[T](queue: queue) + +proc send*[T](self: Sender[T]; t: sink T) = + self.queue[].add t + +proc newChannel*(): Sender[int] = + let queue = newSharedPtr(newSeq[int]()) + result = newSender(queue) + + +var + p: Thread[Sender[int]] + +proc threadFn(tx: Sender[int]) = + send tx, 0 + +proc multiThreadedChannel = + let tx = newChannel() + createThread(p, threadFn, tx) + joinThread(p) + +multiThreadedChannel() |