[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platform Isolate #136314

Closed
liamappelbe opened this issue Oct 11, 2023 · 18 comments
Closed

Platform Isolate #136314

liamappelbe opened this issue Oct 11, 2023 · 18 comments
Assignees
Labels
c: new feature Nothing broken; request for a new capability c: proposal A detailed proposal for a change to Flutter engine flutter/engine repository. See also e: labels. P1 High-priority issues at the top of the work list r: fixed Issue is closed as already fixed in a newer version team-engine Owned by Engine team triaged-engine Triaged by Engine team

Comments

@liamappelbe
Copy link
Contributor
liamappelbe commented Oct 11, 2023

This is a tracking bug for the Platform Isolate feature. The design details are still being worked out, but the general idea is to provide a way of using FFI to invoke native APIs that can only be be called from the platform thread.

Some related bugs: #113099, #28310, dart-lang/sdk#52106, dart-lang/sdk#38315, dart-lang/sdk#42570, dart-lang/sdk#46943, dart-lang/native#463

Remaining work tasks after initial PR landed

@insinfo
Copy link
insinfo commented Jan 16, 2024

I believe that perhaps this could solve the problem of low-level audio API callbacks in the system that today cannot be called with dart ffi

@liamappelbe
Copy link
Contributor Author

@insinfo Only if the audio API calls those callbacks on the platform thread. Audio APIs often create their own internal thread dedicated to audio rendering, and in that case platform isolates wouldn't help.

copybara-service bot pushed a commit to dart-lang/sdk that referenced this issue Feb 15, 2024
This is needed to prevent users from closing the platform isolate.

Bug: flutter/flutter#136314
Change-Id: I98ab0a847dad245a1f1d6c16e96f2f4add39a84f
TEST=runtime/vm/isolate_test.cc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352760
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Liam Appelbe <liama@google.com>
liamappelbe added a commit to flutter/engine that referenced this issue Mar 4, 2024
This is a prototype of the [PlatformIsolate
API](flutter/flutter#136314).

**UPDATE (Jan 25):** The PR is ready for review. PTAL.

The `PlatformIsolate` creation flow is:

1. `PlatformIsolate.spawn` running on parent isolate
(platform_isolate.dart)
    a. Create `isolateReadyPort`
    b. `PlatformIsolateNativeApi::Spawn` (platform_isolate.cc)
    c. `DartIsolate::CreatePlatformIsolate` (dart_isolate.cc)
d. Isolate created. Entry point invocation task dispatched to platform
thread
    e. `PlatformIsolate.spawn` returns a `Future<Isolate>`
2. On the platform thread, `_platformIsolateMain` is invoked in the
platform isolate
    a. Create `entryPointPort`
b. Send `Isolate.current` metadata and `entryPointPort` back to the
parent isolate via `isolateReadyPort`
3. Back in the parent isolate, `isolateReadyPort.handler` is invoked
a. Send the user's `entryPoint` and `message` to the platform isolate
via `entryPointPort`
b. Use received isolate metadata to create a new `Isolate` representing
the platform isolate and complete the `Future<Isolate>`
4. In the platform isolate, `entryPointPort.handler` is invoked
    a. Run the user's `entryPoint(message)`

The engine shutdown flow is handled by `PlatformIsolateManager`, which
maintains a set of running platform isolates.
@nadaeltorgoman
Copy link

I still have a problem with that

@halildurmus
Copy link
halildurmus commented Mar 19, 2024

@liamappelbe I wanted to use the runOnPlatformThread function but it appears to be not defined.

I can see the platform_isolate.dart file defined in the dart:ui library:

Screenshot 2024-03-19 201614

However, it's missing in the ui folder:

Screenshot 2024-03-19 202057

Edit: I'm curious if this issue might be linked to the absence of an entry for platform_isolate.dart in the dart_ui.gni file.

The output of flutter --version:

Flutter 3.21.0-10.0.pre.57 • channel master • https://github.com/flutter/flutter.git
Framework • revision 3236957f02 (31 minutes ago) • 2024-03-20 01:00:24 +0800
Engine • revision 59138d5f8e
Tools • Dart 3.4.0 (build 3.4.0-247.0.dev) • DevTools 2.34.0-dev.5

@liamappelbe
Copy link
Contributor Author

Edit: I'm curious if this issue might be linked to the absence of an entry for platform_isolate.dart in the dart_ui.gni file.

Maybe. I'm not a regular contributor to the engine, so I'm not sure what plumbing is needed when a new file is added. I'm surprised this wasn't caught by CI though. @jason-simmons should I add platform_isolate.dart to dart_ui.gni?

jason-simmons added a commit to jason-simmons/flutter_engine that referenced this issue Mar 19, 2024
…package

This makes the API available to Flutter framework users.

See flutter/flutter#136314
@jason-simmons
Copy link
Member

Sent a PR to add it to dart_ui.gni: flutter/engine#51538

auto-submit bot pushed a commit to flutter/engine that referenced this issue Mar 20, 2024
…package (#51538)

This makes the API available to Flutter framework users.

See flutter/flutter#136314
@halildurmus
Copy link

The Platform Isolate API is now available on the master channel.

I've tried calling the runOnPlatformThread function in a Flutter Counter app but the app crashed with this error:

[FATAL:flutter/fml/message_loop.cc(21)] Check failed: loop != nullptr. MessageLoop::EnsureInitializedForCurrentThread was not called on this thread prior to message loop use.

It doesn't matter what you do in the function that you pass to the runOnPlatformThread function. Even calling it this way crashes the app with the above error:

  void _incrementCounter() async {
    await runOnPlatformThread(() {});
    // ...
  }

@jason-simmons
Copy link
Member

What platform did this happen on?

From the screenshot in #136314 (comment) it looks like you're running on Windows.

The runOnPlatformThread API is not supported on embedders such as Linux and Windows that use a custom task runner for the platform thread (see flutter/engine#48551 (comment))

I'm planning to add a Flutter engine flag that embedders can use to indicate whether they support this API.

@halildurmus
Copy link

What platform did this happen on?

From the screenshot in #136314 (comment) it looks like you're running on Windows.

Yes, I tested this on Windows.

The runOnPlatformThread API is not supported on embedders such as Linux and Windows that use a custom task runner for the platform thread (see flutter/engine#48551 (comment))

I'm planning to add a Flutter engine flag that embedders can use to indicate whether they support this API.

I see. Thanks for the explanation.

@liamappelbe
Copy link
Contributor Author

@halildurmus What's your use case? Windows APIs aren't usually thread locked

@halildurmus
Copy link
halildurmus commented Mar 20, 2024

@halildurmus What's your use case? Windows APIs aren't usually thread locked

I think I've found a Win32 API (ShowCursor) that needs to be called on the platform thread in order to work (see dart-windows/win32#313).

I've confirmed that it works (hides the cursor) if I call the API inside the Windows runner (windows\runner\main.cpp).

I suspect there may be many similar APIs in the Win32 API that need to be called on the platform thread.

@jason-simmons
Copy link
Member

Looked at this again and found a viable way to make the current platform isolates implementation work with the task runner design used on Linux and Windows.

Proposed a PR: flutter/engine#51573

@halildurmus
Copy link

Not entirely sure whether the changes made in flutter/engine#51573 were intended to completely resolve the problems on Linux and Windows but after trying again, I still encountered the same error. I even gave it a shot on Linux, but it didn't work there either.

@jason-simmons
Copy link
Member

No - that PR is not a complete solution.

There is still the issue of supporting embedders where the platform thread does not have a message loop (see flutter/engine#48551 (comment)).

With flutter/engine#51573 a call to runOnPlatformThread in a host_debug_unopt Linux or Windows desktop engine build will execute the function on the platform thread.

But that only works because an internal debugging feature (DebugTaskRunnerChecker) is creating a message loop on the platform thread. Production builds will not enable this, so platform isolate initialization will fail with the MessageLoop::EnsureInitializedForCurrentThread was not called assertion seen above.

The Linux and Windows embedders will need to solve this in order to enable support for platform isolates.

The message loop is needed because UIDartState is trying to install a callback that runs after each message in order to execute Dart microtasks. If platform isolates need to support microtasks, then the embedder must create a message loop on the platform thread and also run the loop and execute this callback.

So until this is resolved I think it makes sense to also add the engine flag that embedders can use to declare whether they support platform isolates.

jason-simmons added a commit to jason-simmons/flutter_engine that referenced this issue Mar 29, 2024
…s available.

Platform isolates are currently supported only on Android and iOS.

See flutter/flutter#136314
auto-submit bot pushed a commit to flutter/engine that referenced this issue Apr 2, 2024
…s available. (#51784)

Platform isolates are currently supported only on Android and iOS.

See flutter/flutter#136314
@orestesgaolin
Copy link
Contributor

Wondering if there's a design doc or summary of what this means to Flutter developers?

@brandon3343
Copy link

May I ask if after this feature is implemented, I will be able to call the native function from the thread where the win32 window was created?

For example, SetWindowSubclass for win32 can only be called from the thread that created the win32 window. SetWindowSubclass can not be used across threads.

So I can't do it with pure dart code at the moment, I need to use platform channels for that.

@liamappelbe
Copy link
Contributor Author

May I ask if after this feature is implemented, I will be able to call the native function from the thread where the win32 window was created?

The feature is already implemented (as runOnPlatformThread), but unfortunately it's only fully supported on iOS and Android. I think there's partial support on windows and linux (debug mode only). See Jason's comment for details.

@liamappelbe
Copy link
Contributor Author

I've split off the remaining bits of work into their own issues. Closing this now.

@danagbemava-nc danagbemava-nc added the r: fixed Issue is closed as already fixed in a newer version label Jun 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: new feature Nothing broken; request for a new capability c: proposal A detailed proposal for a change to Flutter engine flutter/engine repository. See also e: labels. P1 High-priority issues at the top of the work list r: fixed Issue is closed as already fixed in a newer version team-engine Owned by Engine team triaged-engine Triaged by Engine team
Projects
None yet
Development

No branches or pull requests

10 participants