urbanairship / airship-flutter

Flutter integration
Other
17 stars 18 forks source link

Crash on launch when using FlutterEngineGroup #189

Closed mnespor closed 5 months ago

mnespor commented 10 months ago

Preliminary Info

What Airship dependencies are you using?

Airship Flutter 7.0.0 Airship iOS SDK 17.3.0

What are the versions of any relevant development tools you are using?

Xcode 15.0 Flutter 3.13.8 iOS 17.0

Report

What unexpected behavior are you seeing?

Crash on plugin registration

What is the expected behavior?

No crash

What are the steps to reproduce the unexpected behavior?

  1. Use Airship Flutter in an add-to-app Flutter project with multiple entry points.
  2. Instantiate multiple engines and add them to an engine group:
    var engineGroup = FlutterEngineGroup(name: "native-apps-flutter", project: nil)

    private lazy var rootEngine = { () -> FlutterEngine in
        // By default, the engine uses main.dart as the entry point. You can run a different entry point if needed:
        // https://flutter.dev/docs/development/add-to-app/ios/add-flutter-screen?tab=vc-swift-tab#dart-entrypoint
        let engine = engineGroup.makeEngine(withEntrypoint: "main", libraryURI: nil)
        engine.run()
        // Used to connect plugins (only if you have plugins with iOS platform code).
        GeneratedPluginRegistrant.register(with: engine)
        return engine
    }()

    private lazy var moduleEngine = { () -> FlutterEngine in
        let engine = engineGroup.makeEngine(withEntrypoint: "showModule", libraryURI: nil)
        engine.run()
        GeneratedPluginRegistrant.register(with: engine)
        return engine
    }()
  1. The multiple GeneratedPluginRegistrant.register() calls will result in SwiftAirshipPlugin.register() being invoked twice. Affected line has a comment added.
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(
            name: "com.airship.flutter/airship",
            binaryMessenger: registrar.messenger()
        )

        Task {
            let stream = await AirshipProxyEventEmitter.shared.pendingEventAdded
            for await event in stream {
                await self.streams[event.type]?.processPendingEvents() // Crash on this line as two `Task`s consume the same `pendingEventAdded` stream
            }
        }

        let instance = SwiftAirshipPlugin()

        registrar.addMethodCallDelegate(instance, channel: channel)

        self.streams.values.forEach { stream in
            stream.register(registrar: registrar)
        }

        registrar.register(AirshipInboxMessageViewFactory(registrar), withId: "com.airship.flutter/InboxMessageView")
        registrar.addApplicationDelegate(instance)
    }

Do you have logging for the issue?

Thread 36: Fatal error: attempt to await next() on more than one task

rlepinski commented 10 months ago

Thanks for the report, I think I might have a quick fix that I should be able to get out this week

rlepinski commented 10 months ago

Could you see if this fix works for you - https://github.com/urbanairship/airship-flutter/tree/GH-189

mnespor commented 10 months ago

@rlepinski Confirmed, the fix works great. Thank you so much!