Skip to content

[vm/ffi] TypedData, Pointer, multiple isolates, and releasing native resources #54885

Open
@dcharkes

Description

@dcharkes

Pointers can be converted into external TypedData with the asTypedList.

When sending messages to other isolates:

  • Pointers are simply an address sent to another isolate.
  • external TypedDatas have their backing buffer copied and a free-finalizer attached.

This means that if a user calls asTypedData first, and then sends to another isolate, all native resources are cleaned up correctly both in the case the message is delivered as well as when the message is not delivered. We're assuming Dart takes ownership of the native memory and attaches a finalizer to free the buffer once it's done using it by calling asTypedList with a finalizer immediately on receiving the pointer from native code.

If the user sends the Pointer to another isolate and converts it to a typed-data on the other end, attaching a finalizer there, the native resource does not get finalized if the message never arrives. But it is faster, because no copies of the backing buffer are made. (The user could start sending messages back and forth between both isolates to acknowledge ownership is transferred from one isolate to the other, but that leads to the byzantine generals problem.)

A third strategy is to use a reference counter in native code and let every isolate call the finalizer. However, this is racy, because the source isolate could GC it's reference to the native resource before a reference on the receiving isolate is created increasing the reference count. Then you'd want to increase the reference account before sending, but that would lead to leaked resources if the message never arrives.

I think we have multiple things we should address here.

  1. We should document the difference between sending Pointers to other isolates and sending TypedDatas created from pointers to other isolates.
  2. We could consider adding NativeFinalizers to sending messages that get run if the message is not delivered. That would enable users to implement the refcounter properly.
  3. We could consider introducing something like a IsolateGroupFinalizable which allows one to attach a NativeFinalizer which will run once every copy of the IsolateGroupFinalizable object has been GCed. This would avoid the need for users to implement their own refcounter. (I feel like we discussed this before, but I can't find the relevant GitHub issue.)

cc @mkustermann @mraleph

I think this is a rather common question that has to be dealt with as soon as somewhat longer FFIcalls are involved that users would like to run on a helper isolate. @craiglabenz

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-vmUse area-vm for VM related issues, including code coverage, and the AOT and JIT backends.library-ffitype-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions