Skip to content

Layout gesture reset crashes when gesture debugging is enabled #1086

Description

@Kyle-Ye

Description

Tapping a view with .onTapGesture can abort an iOS app when gesture debugging is enabled with _eventDebugTriggers = .all. The crash occurs when a layout gesture resets a terminal child and evaluates its debug data.

Reproduction

Run the OpenSwiftUI iOS example with this ContentView, then tap "Hello, world!":

import OpenSwiftUI

struct ContentView: View {
    init() {
        _eventDebugTriggers = .all
    }

    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
                .onTapGesture {
                    print("A")
                }
            Color.red
                .onTapGesture {
                    print("B")
                }
        }
        .padding()
    }
}

Expected behavior

The tap completes, and gesture debug data remains available without a crash.

Actual behavior

The app aborts with a Swift exclusivity violation:

Simultaneous accesses to 0x6000037182e0, but modification requires exclusive access.
Previous access (a modification) started at OpenSwiftUICore`LayoutGestureBox.resetTerminalChildren<A>(gesture:) + 916 (0x107665884).
Current access (a read) started at:
0    libswiftCore.dylib                 swift::runtime::AccessSet::insert
1    libswiftCore.dylib                 swift_beginAccess
2    OpenSwiftUICore                    LayoutChildSeed.value.getter + 140
3    OpenSwiftUICore                    protocol witness for Rule.value.getter in conformance LayoutChildSeed<A> + 48
4    AttributeGraph                    __swift_memcpy56_8

Cause and scope

children[index].reset() holds a modifying access to the children array. During the reset, reading lazy gesture debug data can make AttributeGraph evaluate LayoutChildSeed.value, which reads the same array and causes the conflict. The same reset pattern is used for terminal children, reset-seed changes, and child removal.

The terminal-reset conflict also reproduces with system SwiftUI on the iOS 18.5 Simulator when SWIFTUI_GESTURE_CONTAINER=0 and gesture debugging is enabled.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: event-gestureEvents, gestures, tracing, or interaction plumbing.impact: crashCrash, assertion, or fatal runtime failure.platform: iOSiOS-specific behavior or support.type: bugSomething is not working correctly.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions