Skip to content

Commit aaaf0c7

Browse files
committed
x.multiwindow: fix AppKit window teardown SIGSEGV in headless Metal CI
The AppKit backend passed window records through nested calls as `mut record &AppKitWindowRecord` (a mutable pointer-to-pointer that also aliases the `mut backend` receiver, since the record lives inside `backend.windows`). Re-passing that `mut &` parameter across `release_window_resources` -> `release_window_drawable_lifetime` / `prepare_window_native_destroy` corrupted the pointer: a valid record address (e.g. 0x8ef0824c8) arrived in the callee as `3`, so reading `record.active_drawable_ticket` faulted at 0x53 (SIGSEGV, exit 11, no output). It surfaced in `multiwindow_buffer_cleanup_d_gg_multiwindow_test.v`'s renderer-initialization-failure probe on macOS CI (`-d sokol_metal`), during `app.stop()` teardown. Pass the record as `mut record AppKitWindowRecord` (V's standard single -indirection by-reference) instead of `mut record &AppKitWindowRecord`, and hand the call sites `mut backend.windows[i]` directly rather than a `&` alias local. Behaviour is unchanged; only the parameter indirection is fixed.
1 parent 364cdab commit aaaf0c7

1 file changed

Lines changed: 19 additions & 20 deletions

File tree

vlib/x/multiwindow/appkit_backend.c.v

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -653,14 +653,14 @@ fn (mut backend AppKitBackend) finish_window_teardown(id WindowId) ! {
653653
return error(err_appkit_application_failed)
654654
}
655655
}
656-
mut record := &backend.windows[index]
657-
released := backend.release_window_resources(mut record, NativeOperationSeed{
656+
seed := NativeOperationSeed{
658657
presence_mask: native_context_has_window | native_context_has_target_generation
659658
call_site: .shutdown_release
660659
scope: .window_target
661-
window: record.id
662-
target_generation: record.render_target_generation
663-
})
660+
window: backend.windows[index].id
661+
target_generation: backend.windows[index].render_target_generation
662+
}
663+
released := backend.release_window_resources(mut backend.windows[index], seed)
664664
if !released {
665665
return error(err_appkit_destroy_window_failed)
666666
}
@@ -960,14 +960,14 @@ fn (mut backend AppKitBackend) stop() ! {
960960
}
961961
mut window_index := 0
962962
for window_index < backend.windows.len {
963-
mut record := &backend.windows[window_index]
964-
released := backend.release_window_resources(mut record, NativeOperationSeed{
963+
seed := NativeOperationSeed{
965964
presence_mask: native_context_has_window | native_context_has_target_generation
966965
call_site: .shutdown_release
967966
scope: .window_target
968-
window: record.id
969-
target_generation: record.render_target_generation
970-
})
967+
window: backend.windows[window_index].id
968+
target_generation: backend.windows[window_index].render_target_generation
969+
}
970+
released := backend.release_window_resources(mut backend.windows[window_index], seed)
971971
if !released {
972972
append_appkit_stop_error(mut errors, err_appkit_destroy_window_failed)
973973
window_index++
@@ -1521,7 +1521,7 @@ fn appkit_pending_start_device_is_empty(pending AppKitPendingStartDevice) bool {
15211521
return pending.value == unsafe { nil } && pending.transaction.ticket_id == 0
15221522
}
15231523

1524-
fn (mut backend AppKitBackend) release_window_drawable_lifetime(mut record &AppKitWindowRecord, mode AppKitWindowDrawableReleaseMode, error_text string) bool {
1524+
fn (mut backend AppKitBackend) release_window_drawable_lifetime(mut record AppKitWindowRecord, mode AppKitWindowDrawableReleaseMode, error_text string) bool {
15251525
if appkit_lifetime_pair_is_empty(record.active_drawable, record.active_drawable_ticket) {
15261526
if mode == .close_frame {
15271527
record.frame_active = false
@@ -1586,8 +1586,7 @@ fn (mut backend AppKitBackend) release_active_frames_lifetime() bool {
15861586
$if darwin {
15871587
mut all_retired := true
15881588
for i in 0 .. backend.windows.len {
1589-
mut record := &backend.windows[i]
1590-
if !backend.release_window_drawable_lifetime(mut record, .close_frame,
1589+
if !backend.release_window_drawable_lifetime(mut backend.windows[i], .close_frame,
15911590
err_appkit_metal_drawable_failed) {
15921591
all_retired = false
15931592
}
@@ -1648,7 +1647,7 @@ fn (mut backend AppKitBackend) release_pending_window_state_lifetime() bool {
16481647
return true
16491648
}
16501649

1651-
fn (mut backend AppKitBackend) prepare_window_native_destroy(mut record &AppKitWindowRecord, seed NativeOperationSeed) bool {
1650+
fn (mut backend AppKitBackend) prepare_window_native_destroy(mut record AppKitWindowRecord, seed NativeOperationSeed) bool {
16521651
$if darwin {
16531652
if record.native_destroyed {
16541653
return true
@@ -1691,7 +1690,7 @@ fn (mut backend AppKitBackend) prepare_window_native_destroy(mut record &AppKitW
16911690
}
16921691
}
16931692

1694-
fn (mut backend AppKitBackend) release_window_resources(mut record &AppKitWindowRecord, seed NativeOperationSeed) bool {
1693+
fn (mut backend AppKitBackend) release_window_resources(mut record AppKitWindowRecord, seed NativeOperationSeed) bool {
16951694
$if darwin {
16961695
if !backend.release_window_drawable_lifetime(mut record, .close_frame,
16971696
err_appkit_metal_drawable_failed) {
@@ -1848,14 +1847,14 @@ fn (mut backend AppKitBackend) release_renderer_lifetime() bool {
18481847
scope: .batch
18491848
})
18501849
for i in 0 .. backend.windows.len {
1851-
mut record := &backend.windows[i]
1852-
_ = backend.release_window_resources(mut record, NativeOperationSeed{
1850+
seed := NativeOperationSeed{
18531851
presence_mask: native_context_has_window | native_context_has_target_generation
18541852
call_site: .shutdown_release
18551853
scope: .window_target
1856-
window: record.id
1857-
target_generation: record.render_target_generation
1858-
})
1854+
window: backend.windows[i].id
1855+
target_generation: backend.windows[i].render_target_generation
1856+
}
1857+
_ = backend.release_window_resources(mut backend.windows[i], seed)
18591858
}
18601859
_ = backend.release_pending_window_state_lifetime()
18611860
_ = backend.release_anchor_state_lifetime(NativeOperationSeed{

0 commit comments

Comments
 (0)