Skip to content

dart:ffi GC finalizers #35770

@dcharkes

Description

@dcharkes

Update 2022:

Available in https://api.dart.dev/stable/2.18.3/dart-ffi/NativeFinalizer-class.html.

Update 2020-06-26:
Finalizers are now available in native code (not yet exposed in Dart):

d.lookupFunction<Void Function(Handle), void Function(Object)>("PassObjectToC");

void attachFinalizer(Object o) => passObjectToC(o);
static void RunFinalizer(void* isolate_callback_data,
                         void* peer) {
  printf("Running finalizer.\n");
}

extern "c" void PassObjectToC(Dart_Handle h) {
  void* peer = 0x0;
  intptr_t size = 8;
  auto finalizable_handle = Dart_NewFinalizableHandle_DL(handle_2, peer, size, RunFinalizer);
}

Use dynamic linking (the _DL suffix) so that the symbols are available in Flutter. See documentation and samples on 7eac9f3 (C code, Dart code).

See more documentation in native_api.h and dart_api_dl.h.

Caveat:

  • The dart optimiser can inline method bodies and fields, which means objects can in some cases be GCed (and their finalizer run) before all methods are done executing. When we expose finalizers in Dart, we will have a solution for this. Workaround: do an ffi call with a Dart_Handle passing that object to native, that will keep it alive until that call (like a reachability fence). Or alternatively use the Dart calling convention to keep the object alive:
    @pragma('vm:never-inline')
    Object reachabilityFence(Object obj) {
      return obj;
    }

==========================================================================================

This issue was originally intended to track exposing finalizers in Dart. (The above code exposes finalizers in C.)

A potential API would be.

/// Return a pointer object that has a finalizer attached to it. When this
/// pointer object is collected by GC the given finalizer is invoked.
///
/// Note: the pointer object passed to the finalizer is not the same as 
/// the pointer object that is returned from [finalizable] - it points
/// to the same memory region but has different identity. 
Pointer<T> finalizable<T>(Pointer<T> p, void finalizer(Pointer<T> ptr)) {

}

However, exposing FFI-specific finalizers in Dart has been superseded by adding finalizers to Dart in general https://github.com/dart-lang/sdk/issues/45455.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-core-librarySDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries.library-ffi

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions