Skip to content

[ffi] Creating an external string with a Dart function from within Dart causes a crash. #50452

Closed
@modulovalue

Description

@modulovalue

I'm trying to create an external string so I can manage the storage of a String outside of Darts heap.

Consider the following example which allocates some memory and calls into Dart_NewExternalUTF16String:

import 'dart:ffi';
import 'package:ffi/ffi.dart' as ffi;

void main() {
  const chars = 5;
  print(
    "> " +
        (DynamicLibrary.executable().lookupFunction<C_Side, Dart_Side>(
          'Dart_NewExternalUTF16String',
        )(
          () {
            final mem = ffi.malloc.allocate<Uint16>(chars * sizeOf<Uint16>());
            mem.asTypedList(chars).fillRange(0, chars, 68);
            return mem;
          }(),
          chars,
          nullptr,
          0,
          Pointer.fromFunction<Dart_HandleFinalizer_Fn>(
            my_finalizer,
          ),
        ) as String),
  );
}

void my_finalizer(
  final Pointer<Void> a,
  final Pointer<Void> b,
) {
  print(
    "Running finalizer.",
  );
}

typedef Dart_HandleFinalizer_Fn = Void Function(Pointer<Void>, Pointer<Void>);

typedef Dart_HandleFinalizer = Pointer<NativeFunction<Dart_HandleFinalizer_Fn>>;

typedef C_Side = Handle Function(
  Pointer<Uint16>,
  Int64,
  Pointer<NativeType>,
  Int64,
  Dart_HandleFinalizer,
);

typedef Dart_Side = Object Function(
  Pointer<Uint16>,
  int,
  Pointer<NativeType>,
  int,
  Dart_HandleFinalizer,
);

I get a string as expected i.e. the print expression outputs 'DDDDD', but the program crashes afterwards with:

> DDDDD

===== CRASH =====
si_signo=Segmentation fault: 11(11), si_code=1, si_addr=0x1069fa000
version=2.19.0-255.2.beta (beta) (Tue Oct 4 13:45:53 2022 +0200) on "macos_x64"
pid=12890, thread=775, isolate_group=main(0x7fe88f018400), isolate=(nil)(0x0)
os=macos, arch=x64, comp=no, sim=no
isolate_instructions=1040e1f40, vm_instructions=1040e1f40
pc 0x00000001069fa000 fp 0x00007ffeebb83820 Unknown symbol
pc 0x000000010427c1dd fp 0x00007ffeebb83890 dart::Isolate::LowLevelCleanup(dart::Isolate*)+0x26d
pc 0x000000010427d900 fp 0x00007ffeebb842d0 dart::Isolate::Shutdown()+0x1c0
pc 0x0000000104855abb fp 0x00007ffeebb84810 Dart_ShutdownIsolate+0xcb
pc 0x00000001040ba163 fp 0x00007ffeebb848b0 dart::bin::RunMainIsolate(char const*, char const*, dart::bin::CommandLineOptions*)+0x2e3
pc 0x00000001040baed2 fp 0x00007ffeebb849f0 dart::bin::main(int, char**)+0x662
pc 0x00000001040bbd69 fp 0x00007ffeebb84a00 main+0x9
pc 0x00007fff736c7085 fp 0x00007ffeebb84a10 start+0x1
-- End of DumpStackTrace
Abort trap: 6

I remember reading somewhere that native finalizers can't call into Dart code. Is that what causes this error?
Does this restriction still apply? (I presume this doesn't have to be case since there are Finalizers now in Dart that support dart functions.)
Or am I using this API incorrectly?

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-questionA question about expected behavior or functionality

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions