-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
How to make Isolate.spawn()
safe
#36648
Comments
Isolate.spawn()
safeIsolate.spawn()
safe
The standalone VM was changed to not use the source code but rather spawn from the kernel files that were used for spawning the parent isolate (see #6610 and the CL https://dart-review.googlesource.com/c/sdk/+/85724). The Isolate reload case is still broken because we don't transitively reload all the isolates but at the minimum we should revert this hot reloaded isolate to behave similar to a spawnUri isolate and allow it to only send/receive messages of primitives or collections of primitives. We have another effort going on to remove spawning of the Service and Kernel isolates from the VM and instead move them out to the embedder, once that is done we can take a look at cleaning up this create callback hook for the spawn case. |
A few reasons the embedder needs to be involved in isolate spawning: The embedder is needed to initialize the native half of core libraries like The embedder is needed to decide which thread the isolate will run on. Before the isolate is made runnable, the embedder may use The embedder may want to enforce some resource limits. The flutter_runner and dart_runner embedders on Fuchsia run independent "components" in the same process. These embedders might try to set total max heap capacities, etc to prevent one component from monopolizing resources. However, I don't think the embedder needs to be involved in loading the Dart code into the isolate. It seems reasonable to me that the VM would do this to guarantee isolates share code, though this probably requires new callbacks with the embedder. |
Thanks for the quick feedback!
Is someone actively working on this? If so, please let me know who, so we can coordinate. Though I believe this is mostly orthogonal to what I want to look into.
That was precisely my thinking as well. I would assume that two additional callbacks would suffice: Similar to the current Though since multiple isolates share the same kernel/jit/aot snapshot buffers, another callback, e.g. This would simplify the embedder code by removing the need to examine
I suppose such resource constraints would apply for all of the component's isolates together (e.g. their sum cannot exceed X MB ram, Y % CPU ...) rather than per isolate? |
An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue #36648 Issue #36097 Change-Id: I82437ac017ca33018d45e02f353b0672db155f6a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105241 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
This reverts commit b75057b. Reason for revert: Caused some failures on app-jit builders Original change's description: > [vm/concurrency] Introduce concept of Isolate Groups > > An Isolate Group (IG) is a collection of isolates which were spawned from the > same source. This allows the VM to: > > * have a guarantee that all isolates within one IG can safely exchange > structured objects (currently we rely on embedder for this > guarantee) > > * hot-reload all isolates together (currently we only reload one > isolate, leaving same-source isolates in inconsistent state) > > * make a shared heap for all isolates from the same IG, which paves > the way for faster communication and sharing of immutable objects. > > All isolates within one IG will share the same IsolateGroupSource. > > **Embedder changes** > > This change makes breaking embedder API changes to support this new > concept of Isolate Groups: The existing isolate lifecycle callbacks > given to Dart_Initialize will become Isolate Group lifecycle callbacks. > A new callback `initialize_isolate` callback will be added which can > initialize a new isolate within an existing IG. > > Existing embedders can be updated by performing the following renames > > Dart_CreateIsolate -> Dart_CreateIsolateGroup > Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback > Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback > Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel > Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData > Dart_IsolateData -> Dart_IsolateGroupData > Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData > Dart_InitializeParams.create -> Dart_InitializeParams.create_group > Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group > Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate > > By default `Isolate.spawn` will cause the creation of a new IG. > > Though an embedder can opt-into supporting multiple isolates within one IG by > providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. > The responsibility of this new callback is to initialize an existing > isolate (which was setup by re-using source code from the spawning > isolate - i.e. the one which used `Isolate.spawn`) by setting native > resolvers, initializing global state, etc. > > Issue #36648 > Issue #36097 > > Change-Id: I82437ac017ca33018d45e02f353b0672db155f6a > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105241 > Commit-Queue: Martin Kustermann <kustermann@google.com> > Reviewed-by: Ryan Macnak <rmacnak@google.com> > Reviewed-by: Alexander Aprelev <aam@google.com> TBR=kustermann@google.com,aam@google.com,rmacnak@google.com Change-Id: Ibd90992a01d61188f27b445c21532e0c46f996ea No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107405 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue #36648 Issue #36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Change-Id: I98277d3d10fe275aa9b8a16b6bdd446bbea0b100 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107506 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
This reverts commit 67ab3be. Reason for revert: Causes non-deterministic failures on front-end bots on Windows with "Isolate creation failed" error. See https://logs.chromium.org/logs/dart/buildbucket/cr-buildbucket.appspot.com/8909292129328681248/+/steps/unit_tests/0/stdout Original change's description: > Reland "[vm/concurrency] Introduce concept of Isolate Groups" > > An Isolate Group (IG) is a collection of isolates which were spawned from the > same source. This allows the VM to: > > * have a guarantee that all isolates within one IG can safely exchange > structured objects (currently we rely on embedder for this > guarantee) > > * hot-reload all isolates together (currently we only reload one > isolate, leaving same-source isolates in inconsistent state) > > * make a shared heap for all isolates from the same IG, which paves > the way for faster communication and sharing of immutable objects. > > All isolates within one IG will share the same IsolateGroupSource. > > **Embedder changes** > > This change makes breaking embedder API changes to support this new > concept of Isolate Groups: The existing isolate lifecycle callbacks > given to Dart_Initialize will become Isolate Group lifecycle callbacks. > A new callback `initialize_isolate` callback will be added which can > initialize a new isolate within an existing IG. > > Existing embedders can be updated by performing the following renames > > Dart_CreateIsolate -> Dart_CreateIsolateGroup > Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback > Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback > Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel > Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData > Dart_IsolateData -> Dart_IsolateGroupData > Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData > Dart_InitializeParams.create -> Dart_InitializeParams.create_group > Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group > Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate > > By default `Isolate.spawn` will cause the creation of a new IG. > > Though an embedder can opt-into supporting multiple isolates within one IG by > providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. > The responsibility of this new callback is to initialize an existing > isolate (which was setup by re-using source code from the spawning > isolate - i.e. the one which used `Isolate.spawn`) by setting native > resolvers, initializing global state, etc. > > Issue #36648 > Issue #36097 > > Original review: https://dart-review.googlesource.com/c/sdk/+/105241 > > Difference to original review: > > * Give each isolate it's own [Loader] (for now) > * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) > * Fix IsolateData memory leak if isolate startup fails > > Change-Id: I98277d3d10fe275aa9b8a16b6bdd446bbea0b100 > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107506 > Commit-Queue: Martin Kustermann <kustermann@google.com> > Reviewed-by: Ryan Macnak <rmacnak@google.com> TBR=kustermann@google.com,aam@google.com,rmacnak@google.com # Not skipping CQ checks because original CL landed > 1 day ago. Change-Id: Ia4e0f4f9fc317499d3570a371c5bdf9aed799e77 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108101 Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
…te Groups" This reverts commit 3d14b75. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue #36648 Issue #36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
As part of #36097 - which enabled isolate groups by-default now, hot-reload of all isolates within a group should be safe (modulo other non-isolate related issues). Closing this. |
Right now
Isolate.spawn()
is implemented by calling out to the embedder, which supplies a Dart_IsolateCreateCallback duringDart_Initialize
.The VM has currently the assumption that isolates spawned via
Isolate.spawn()
have the exact same source code and the same representation of source code (e.g. snapshot, ...) because message sending internally relies on the isolates to have the same class id numbering.Unfortunately this is not safe because:
create
callback.Is there a need for the embedder to implement
Isolate.spawn()
- why can't the VM do that internally (by re-using the same kernel/jit/aot snapshot used for the original isolate)?If the only reason is to enable the embedder to disallow isolate spawning we could have a callback to the embedder for asking permission to spawn but the implementation for spawning can be inside the VM.
@rmacnak-google Do you see any reason why we could not change this?
Related issues where users have already ran into this:
The text was updated successfully, but these errors were encountered: