Skip to content

Conversation

@kolkov
Copy link
Contributor

@kolkov kolkov commented Jan 5, 2026

Problem

Intermittent panics in CreateRenderPipeline on macOS CI:

panic: ...
github.com/gogpu/wgpu/hal/metal.(*AutoreleasePool).Drain
    hal/metal/objc.go:401
github.com/gogpu/wgpu/hal/metal.(*Device).CreateRenderPipeline.deferwrap1
    hal/metal/device.go:468

Root Cause

NSString() function used stringWithUTF8String: which returns an autoreleased object (+0 retain count, owned by autorelease pool).

Callers then called Release() on these objects:

  1. Release(label) decrements retain count below 0 (invalid)
  2. pool.Drain() tries to release already-freed object
  3. Crash (double-free)

Fix

Use alloc/initWithUTF8String: instead of stringWithUTF8String::

  • Returns +1 retained object owned by caller
  • Caller's Release() correctly decrements to 0 and frees
  • pool.Drain() has nothing extra to release

Objective-C Memory Management Rules

Method Pattern Return Ownership
alloc, new, copy, mutableCopy +1 retained Caller owns, must release
stringWith..., convenience methods +0 autoreleased Pool owns, don't release

Test Plan

  • go build ./hal/metal/... — Pass
  • golangci-lint run ./hal/metal/... — 0 issues
  • CI — Wait for all checks

Problem:
- NSString() used stringWithUTF8String: which returns autoreleased object
- Callers then called Release() on these objects
- When autorelease pool drained, it released already-freed objects
- Caused intermittent panics in CreateRenderPipeline on macOS CI

Root cause:
- stringWithUTF8String: returns +0 autoreleased object (owned by pool)
- Manual Release() decrements retain count below 0
- pool.Drain() tries to release invalid object = crash

Fix:
- Use alloc/initWithUTF8String: instead of stringWithUTF8String:
- Returns +1 retained object owned by caller
- Caller's Release() correctly decrements to 0 and frees
- pool.Drain() has nothing extra to release

Reference: Objective-C Memory Management Rules
- alloc/init returns +1 retained
- convenience methods (stringWith...) return +0 autoreleased
@kolkov kolkov merged commit b21557d into main Jan 5, 2026
20 checks passed
@kolkov kolkov deleted the fix/metal-nsstring-double-free branch January 5, 2026 12:29
kolkov added a commit that referenced this pull request Jan 5, 2026
- Document NSString double-free fix (#39)
- Update version status to v0.9.2
kolkov added a commit that referenced this pull request Jan 5, 2026
- Document NSString double-free fix (#39)
- Update version status to v0.9.2
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.

2 participants