Crash when killing isolate which is getting application documents directory (path_provider)

This issue has been tracked since 2023-03-17.

I've been experiencing Fatal signal 6 (SIGABRT) crashes when using isolates (the 3.7 version of isolates using the new isolate background channels). I have a piece of long running background work which I run in an isolate. For my scenario, it may be called multiple times, but I don't want multiple instances of the task running at the same time, so I use a bool flag to indicate if the task is already running. If it is, I send a kill request to the isolate, and wait until the stream ends, before spawning a new isolate.

After some experimentation the crash only seems to happen when getApplicationDocumentsDirectory() is called (so I suspect path_provider is the cause?), and only when there is a running isolate on which I call kill(). Beyond that I'm struggling to figure out exactly what causes the crash, beyond the rather cryptic message [FATAL:flutter/lib/ui/window/platform_message_response_dart_port.cc(53)] Check failed: did_send.

My minimal reproducible example which just calls getApplicationDocumentsDirectory() in a loop reliably crashes. Just run it and it will crash. See below for the error, and the full code. I'm using Flutter 3.7.5 and reproducible on Android emulator API 33 and on a real Pixel 2. Not yet tested on ios.

Alternatively if I am just doing something stupid in my code would appreciate help a better way to wait until a previous isolate has ended before running another one. See the code example below. Thanks!

log

> Launching lib\main.dart on sdk gphone64 x86 64 in debug mode...
> Running Gradle task 'assembleDebug'...
> √  Built build\app\outputs\flutter-apk\app-debug.apk.
> Installing build\app\outputs\flutter-apk\app-debug.apk...
> Debug service listening on ws://127.0.0.1:51721/1IrI36WPWjw=/ws
> Syncing files to device sdk gphone64 x86 64...
> E/SurfaceSyncer( 4351): Failed to find sync for id=0
> W/Parcel  ( 4351): Expecting binder but got null!
> I/flutter ( 4351): Request for work
> I/flutter ( 4351): Request for work
> I/flutter ( 4351): Waiting for previous isolate to die
> F/flutter ( 4351): [FATAL:flutter/lib/ui/window/platform_message_response_dart_port.cc(53)] Check failed: did_send. 
> F/libc    ( 4351): Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 4663 (flutter-worker-), pid 4351 (ple.isolate_bug)
> Build fingerprint: 'google/sdk_gphone64_x86_64/emu64x:13/TE1A.220922.012/9302419:userdebug/dev-keys'
> Revision: '0'
> ABI: 'x86_64'
> Timestamp: 2023-03-17 12:17:46.076385000+0000
> Process uptime: 19s
> Cmdline: com.example.isolate_bug
> pid: 4351, tid: 4663, name: flutter-worker-  >>> com.example.isolate_bug <<<
> uid: 10159
> signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
> Abort message: '[FATAL:flutter/lib/ui/window/platform_message_response_dart_port.cc(53)] Check failed: did_send. '
>     rax 0000000000000000  rbx 00000000000010ff  rcx 00007d9a074086ff  rdx 0000000000000006
>     r8  0000000000000000  r9  0000000000000000  r10 00007d95f74e7ee0  r11 0000000000000203
>     r12 00007d95f74e8030  r13 00007d95f74e81f0  r14 00007d95f74e7ed8  r15 0000000000001237
>     rdi 00000000000010ff  rsi 0000000000001237
>     rbp 0000000000000007  rsp 00007d95f74e7ed0  rip 00007d9a074086ff
> backtrace:
>       #00 pc 000000000005f6ff  /apex/com.android.runtime/lib64/bionic/libc.so (abort+191) (BuildId: 007cb2313464df63debf8020e631c990)
>       #01 pc 0000000001692a95  /data/app/~~zCrERtfMrMQ4rm94aJs5eQ==/com.example.isolate_bug-whCKcGAaOVoR89VOA5XpiQ==/lib/x86_64/libflutter.so (BuildId: 02da83f7838015562f8e982f4e1381e8aa6dd508)
>       #02 pc 00000000016b940a  /data/app/~~zCrERtfMrMQ4rm94aJs5eQ==/com.example.isolate_bug-whCKcGAaOVoR89VOA5XpiQ==/lib/x86_64/libflutter.so (BuildId: 02da83f7838015562f8e982f4e1381e8aa6dd508)
>       #03 pc 0000000001accb29  /data/app/~~zCrERtfMrMQ4rm94aJs5eQ==/com.example.isolate_bug-whCKcGAaOVoR89VOA5XpiQ==/lib/x86_64/libflutter.so (BuildId: 02da83f7838015562f8e982f4e1381e8aa6dd508)
>       #04 pc 0000000001699adf  /data/app/~~zCrERtfMrMQ4rm94aJs5eQ==/com.example.isolate_bug-whCKcGAaOVoR89VOA5XpiQ==/lib/x86_64/libflutter.so (BuildId: 02da83f7838015562f8e982f4e1381e8aa6dd508)
>       #05 pc 000000000169d72e  /data/app/~~zCrERtfMrMQ4rm94aJs5eQ==/com.example.isolate_bug-whCKcGAaOVoR89VOA5XpiQ==/lib/x86_64/libflutter.so (BuildId: 02da83f7838015562f8e982f4e1381e8aa6dd508)
>       #06 pc 000000000037d70b  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+219) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #07 pc 0000000002015494  /memfd:jit-cache (deleted) (io.flutter.embedding.engine.FlutterJNI.invokePlatformMessageResponseCallback+404)
>       #08 pc 000000000201ce5e  /memfd:jit-cache (deleted) (io.flutter.embedding.engine.dart.DartMessenger$Reply.reply+350)
>       #09 pc 000000000201bacf  /memfd:jit-cache (deleted) (io.flutter.plugin.common.BasicMessageChannel$IncomingMessageHandler$1.reply+271)
>       #10 pc 000000000201b5da  /memfd:jit-cache (deleted) (io.flutter.plugins.pathprovider.Messages$PathProviderApi$-CC.lambda$setup$2+458)
>       #11 pc 0000000000368c95  /apex/com.android.art/lib64/libart.so (nterp_helper+165) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #12 pc 0000000000148080  [anon:dalvik-classes.dex extracted in memory from /data/app/~~zCrERtfMrMQ4rm94aJs5eQ==/com.example.isolate_bug-whCKcGAaOVoR89VOA5XpiQ==/base.apk] (io.flutter.plugins.pathprovider.Messages$PathProviderApi$$ExternalSyntheticLambda2.onMessage+4)
>       #13 pc 0000000002017f13  /memfd:jit-cache (deleted) (io.flutter.plugin.common.BasicMessageChannel$IncomingMessageHandler.onMessage+339)
>       #14 pc 0000000002017b99  /memfd:jit-cache (deleted) (io.flutter.embedding.engine.dart.DartMessenger.invokeHandler+361)
>       #15 pc 000000000201301c  /memfd:jit-cache (deleted) (io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger+556)
>       #16 pc 0000000002019156  /memfd:jit-cache (deleted) (io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run+214)
>       #17 pc 00000000020158b1  /memfd:jit-cache (deleted) (io.flutter.embedding.engine.dart.DartMessenger$SerialTaskQueue.flush+305)
>       #18 pc 0000000000369aed  /apex/com.android.art/lib64/libart.so (nterp_helper+3837) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #19 pc 00000000001325ac  [anon:dalvik-classes.dex extracted in memory from /data/app/~~zCrERtfMrMQ4rm94aJs5eQ==/com.example.isolate_bug-whCKcGAaOVoR89VOA5XpiQ==/base.apk] (io.flutter.embedding.engine.dart.DartMessenger$SerialTaskQueue.lambda$dispatch$0$io-flutter-embedding-engine-dart-DartMessenger$SerialTaskQueue+0)
>       #20 pc 0000000000369a88  /apex/com.android.art/lib64/libart.so (nterp_helper+3736) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #21 pc 0000000000132440  [anon:dalvik-classes.dex extracted in memory from /data/app/~~zCrERtfMrMQ4rm94aJs5eQ==/com.example.isolate_bug-whCKcGAaOVoR89VOA5XpiQ==/base.apk] (io.flutter.embedding.engine.dart.DartMessenger$SerialTaskQueue$$ExternalSyntheticLambda0.run+4)
>       #22 pc 0000000002016579  /memfd:jit-cache (deleted) (java.util.concurrent.ThreadPoolExecutor.runWorker+633)
>       #23 pc 0000000000369aed  /apex/com.android.art/lib64/libart.so (nterp_helper+3837) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #24 pc 0000000000221334  /apex/com.android.art/javalib/core-oj.jar (java.util.concurrent.ThreadPoolExecutor$Worker.run+4)
>       #25 pc 000000000036a7e5  /apex/com.android.art/lib64/libart.so (nterp_helper+7157) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #26 pc 00000000000f6740  /apex/com.android.art/javalib/core-oj.jar (java.lang.Thread.run+8)
>       #27 pc 00000000003725c4  /apex/com.android.art/lib64/libart.so (art_quick_invoke_stub+756) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #28 pc 00000000003f21a6  /apex/com.android.art/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+214) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #29 pc 00000000007e617e  /apex/com.android.art/lib64/libart.so (art::JValue art::InvokeVirtualOrInterfaceWithJValues<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, jvalue const*)+478) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #30 pc 000000000083a91c  /apex/com.android.art/lib64/libart.so (art::Thread::CreateCallback(void*)+1404) (BuildId: 44bc52550248fc712a381bef164b75c7)
>       #31 pc 00000000000ccd2a  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+58) (BuildId: 007cb2313464df63debf8020e631c990)
>       #32 pc 0000000000060d37  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+55) (BuildId: 007cb2313464df63debf8020e631c990)
> Lost connection to device.

pubspec.yaml

name: isolate_bug
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
  sdk: '>=2.19.2 <3.0.0'

dependencies:
  flutter:
    sdk: flutter

  path_provider: ^2.0.13

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:

main.dart

import 'dart:async';
import 'dart:isolate';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {

  const Home();

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {

  Isolate? _isolate;
  bool _isRunning = false;

  @override
  void initState() {

    Timer.periodic(Duration(seconds: 3), (_) async {
      print('Request for work');

      if(_isRunning) {
        _isolate?.kill();
        while(true) {
          print('Waiting for previous isolate to die');
          await Future.delayed(Duration(milliseconds: 500), () {});
          if(!_isRunning) {
            break;
          }
        }
      }

      final responsePort = ReceivePort();
      _isolate = await Isolate.spawn(
        _isolateEntryPoint,
        [RootIsolateToken.instance!, responsePort.sendPort],
      );
      _isRunning = true;
      responsePort.listen((message) {
        print("Response: $message");
        _isRunning = false;
      });
    });

    super.initState();
  }

  static _isolateEntryPoint(List args) async {
    BackgroundIsolateBinaryMessenger.ensureInitialized(args[0]);
    SendPort sendPort = args[1];

    while(true) {
      await getApplicationDocumentsDirectory();
    }

    Isolate.exit(sendPort, 'end');
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold();
  }
}
darshankawar wrote this answer on 2023-03-17

@jamesncl
Can you try this and see if it helps in your case ?

jamesncl wrote this answer on 2023-03-17

@darshankawar yes that works! Thank you. So, is this expected behaviour if you don't call this method?

static _isolateEntryPoint(List args) async {
    BackgroundIsolateBinaryMessenger.ensureInitialized(args[0]);
    DartPluginRegistrant.ensureInitialized();  // <- this works
    SendPort sendPort = args[1];

    while(true) {
      await getApplicationDocumentsDirectory();
    }

    Isolate.exit(sendPort, 'end');
  }
More Details About Repo
Owner Name flutter
Repo Name flutter
Full Name flutter/flutter
Language Dart
Created Date 2015-03-06
Updated Date 2023-03-30
Star Count 151602
Watcher Count 3555
Fork Count 25000
Issue Count 11498

YOU MAY BE INTERESTED

Issue Title Created Date Updated Date