summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2023-10-05 01:41:39 +0800
committerGitHub <noreply@github.com>2023-10-04 19:41:39 +0200
commitf2f0b3e25d976446e657cee7157591ce587624fd (patch)
tree22145efb9711e4f6081ff3ff3495c3f21d6d1190
parentf4a623dadf1a5ba287dbb55893ab70d1d6638c3f (diff)
downloadNim-f2f0b3e25d976446e657cee7157591ce587624fd.tar.gz
fixes #22711; Check atomicArc for atomic destroy race condition (#22788)
fixes #22711

Per @elcritch's awesome solution
-rw-r--r--lib/system/arc.nim23
1 files changed, 15 insertions, 8 deletions
diff --git a/lib/system/arc.nim b/lib/system/arc.nim
index 0624bd4e3..b49a6a63b 100644
--- a/lib/system/arc.nim
+++ b/lib/system/arc.nim
@@ -202,15 +202,22 @@ proc nimDecRefIsLast(p: pointer): bool {.compilerRtl, inl.} =
         writeStackTrace()
         cfprintf(cstderr, "[DecRef] %p %ld\n", p, cell.count)
 
-    if cell.count == 0:
-      result = true
-      when traceCollector:
-        cprintf("[ABOUT TO DESTROY] %p\n", cell)
+    when defined(gcAtomicArc) and hasThreadSupport:
+      # `atomicDec` returns the new value
+      if atomicDec(cell.rc, rcIncrement) == -1:
+        result = true
+        when traceCollector:
+          cprintf("[ABOUT TO DESTROY] %p\n", cell)
     else:
-      decrement cell
-      # According to Lins it's correct to do nothing else here.
-      when traceCollector:
-        cprintf("[DECREF] %p\n", cell)
+      if cell.count == 0:
+        result = true
+        when traceCollector:
+          cprintf("[ABOUT TO DESTROY] %p\n", cell)
+      else:
+        decrement cell
+        # According to Lins it's correct to do nothing else here.
+        when traceCollector:
+          cprintf("[DECREF] %p\n", cell)
 
 proc GC_unref*[T](x: ref T) =
   ## New runtime only supports this operation for 'ref T'.