escaping-block-regression

command
v0.6.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

escaping-block-regression demonstrates an ObjC API pattern that broke before applegen learned to skip `defer block.Release()` for escaping blocks.

MTLCommandBuffer.AddCompletedHandler retains the supplied block and invokes it on GPU completion, possibly after the calling Go function has returned. The pre-fix generator emitted:

func (o MTLCommandBufferObject) AddCompletedHandler(block ...) {
    _block0 := objc.NewBlock(...)
    defer _block0.Release()    // <-- decrements refcount before Metal fires the block
    objc.Send(...)
}

In practice Metal performs a synchronous `[block copy]` inside the addCompletedHandler: call so the defer leaves refcount >= 1 and the handler fires. But the pattern was a latent use-after-free for any framework that defers the copy (e.g. AVAudioEngine.installTapOnBus:), and even for Metal the dispose-on-zero-refcount removes the Go closure from purego's cache, leaving a window for crashes under GC pressure.

Post-fix (appledocs c09228c541) the generator omits the defer for selectors matching install*/set*Block:/set*Handler:/add*Handler:/ subscribe*/register*/observe*. This program submits many command buffers with completion handlers, forces GC between submission and completion, and asserts that every handler fired.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL