swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.3k stars 10.34k forks source link

@objc @MainActor selector crashes when called from NotificationCenter #74037

Open benpious opened 3 months ago

benpious commented 3 months ago

Description

NotificationCenter doesn't seem to know how to call selectors on actor.

It's not clear to me why actor is even allowed to have @objc annotated members, it only seems to allow this when they're async, which seems like a bug in and of itself to me.

Reproduction

import Foundation

actor MyActor {

    init() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(f),
            name: .init("test"),
            object: nil
        )
    }

    @objc
    func f() async {
        print("test")
    }

}

let a = MyActor()
NotificationCenter.default.post(.init(name: Notification.Name(rawValue: "test")))
await Task.yield()

Stack dump

#0  0x000000018e9d2b28 in _Block_copy ()
#1  0x0000000100002f44 in @objc MyActor.f() ()
#2  0x000000018edab144 in __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ ()
#3  0x000000018ee3f3d8 in ___CFXRegistrationPost_block_invoke ()
#4  0x000000018ee3f320 in _CFXRegistrationPost ()
#5  0x000000018ed79678 in _CFXNotificationPost ()
#6  0x00000001000026b4 in async_Main at /Users/benpious/Documents/ObjcActor/ObjcActor/main.swift:29
#7  0x0000000100002814 in thunk for @escaping @convention(thin) @async () -> () ()
#8  0x000000010000293c in partial apply for thunk for @escaping @convention(thin) @async () -> () ()

Expected behavior

The compiler rejects this code, or no crash.

Environment

Swift 5.10, the version that shipped w/Xcode 15.4. I also have a Swift 6 nightly from a week or two ago that crashes with a slightly different stack trace.

Additional information

No response

benpious commented 3 months ago

Tried it a few more times, seems like the example is flaky. Mostly it crashes, but sometimes it runs successfully. Adding @MainActor to f makes it crash more reliably.