Skip to content

Free resized buffers with release, not free - #684

Merged
maleadt merged 1 commit into
mainfrom
tb/resize-release
Oct 14, 2026
Merged

maleadt merged 1 commit into
mainfrom
tb/resize-release

Conversation

@maleadt

@maleadt maleadt commented Oct 13, 2026

Copy link
Copy Markdown
Member

The buffer that resize! allocates was freed by a finalizer calling free(buf) instead of release(buf), as the array constructor does. That bypassed the allocation accounting used by the proactive-GC heuristics, the queue synchronization on the LTS stack that keeps NEO from unmapping memory with work in flight, and the blocking free policy. It also broke arrays resized to zero length: release skips empty buffers, while free passed the null pointer to zeMemFree and threw ZE_RESULT_ERROR_INVALID_ARGUMENT.

Fixes #667

The buffer allocated by resize! was freed with a bare free(), bypassing
everything release() does: decrementing the allocation counter used by the
proactive-GC heuristics, synchronizing queues before freeing on the LTS stack,
using the blocking free policy, and skipping empty buffers. The latter made
freeing an array resized to zero length throw ZE_RESULT_ERROR_INVALID_ARGUMENT.

Fixes #667
@github-actions

Copy link
Copy Markdown
Contributor

Your PR requires formatting changes to meet the project's style guidelines.
Please consider running Runic (git runic main) to apply these changes.

Click here to view the suggested changes.
diff --git a/test/array.jl b/test/array.jl
index c09cfbd..e2b714c 100644
--- a/test/array.jl
+++ b/test/array.jl
@@ -210,21 +210,21 @@ end
   resize!(b, 1)
   @test length(b) == 1
 
-  # resized buffers are released through the pool, like freshly allocated ones
-  c = oneArray{Float32}(undef, 4)
-  resize!(c, 0)
-  oneAPI.unsafe_free!(c)
-
-  GC.enable(false)
-  try
-    d = oneArray{Float32}(undef, 1024)
-    before = oneAPI._allocated_bytes[]
-    resize!(d, 1 << 20)
-    oneAPI.unsafe_free!(d)
-    @test oneAPI._allocated_bytes[] == before - sizeof(Float32) * 1024
-  finally
-    GC.enable(true)
-  end
+    # resized buffers are released through the pool, like freshly allocated ones
+    c = oneArray{Float32}(undef, 4)
+    resize!(c, 0)
+    oneAPI.unsafe_free!(c)
+
+    GC.enable(false)
+    try
+        d = oneArray{Float32}(undef, 1024)
+        before = oneAPI._allocated_bytes[]
+        resize!(d, 1 << 20)
+        oneAPI.unsafe_free!(d)
+        @test oneAPI._allocated_bytes[] == before - sizeof(Float32) * 1024
+    finally
+        GC.enable(true)
+    end
 end
 
 # Reductions and scans come from GPUArrays (AcceleratedKernels). oneAPI used to work around

@codecov

codecov Bot commented Oct 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.58%. Comparing base (fa0f23a) to head (15bd554).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #684      +/-   ##
==========================================
- Coverage   81.17%   79.58%   -1.59%     
==========================================
  Files          52       51       -1     
  Lines        4085     3953     -132     
==========================================
- Hits         3316     3146     -170     
- Misses        769      807      +38     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@maleadt
maleadt merged commit 744939b into main Oct 14, 2026
4 of 5 checks passed
@maleadt
maleadt deleted the tb/resize-release branch October 14, 2026 08:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

resize! frees its new buffer with free instead of release

1 participant