Skip to content
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

Async execution freezes after hitting a breakpoint #37312

Closed
bkonyi opened this issue Jun 19, 2019 · 5 comments
Closed

Async execution freezes after hitting a breakpoint #37312

bkonyi opened this issue Jun 19, 2019 · 5 comments
Assignees
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. vm-debugger

Comments

@bkonyi
Copy link
Contributor

bkonyi commented Jun 19, 2019

From Dart-Code/Dart-Code#1801:

After reaching a breakpoint, it looks like async execution stops working, where regular execution still works. It's easier to explain on example.

  1. Run code attached below.
  2. Add the breakpoint in build method.
  3. Reach the breakpoint and press continue.
  4. If this worked fine, after continuing you would reach the breakpoint again, and again... but it doesn't, it just stops.
  5. Remove the breakpoint - counter starts again.
  6. Add breakpoint again and continue when it's reached.
  7. Press Increment button - you should reach the breakpoint again, but only once.
  8. Press Increment with delay button - you will not reach the breakpoint because it contains await inside.
  9. Try to hot restart - you will reach the breakpoint again and then hot restart will not finish.

Additional notes:

  1. Android Studio does not have this problem.
  2. The breakpoint must be inside build method, breakpoint inside increment method works ok.
  3. It kinda looks like app is paused on breakpoint but VSCode does not show it. That's why removing it fixes the problem.
  4. Maybe it would be good idea to detach breakpoints during hot restart and attach them again after it's finished. Reaching a breakpoint during hot restart seems to break it completely and require cold restart.
import 'package:flutter/material.dart';

Future<void> main() async {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var _counter = 0;

  @override
  void initState() {
    super.initState();
    update();
  }

  void update() {
    increment();
    Future.delayed(Duration(milliseconds: 100)).then((_) => update());
  }

  void increment() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // add breakpoint here
    return MaterialApp(
      home: Container(
        color: Colors.white,
        alignment: Alignment.center,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text(_counter.toString()),
            FlatButton(
              child: Text('Increment'),
              onPressed: increment,
            )
          ],
        ),
      ),
    );
  }
}

flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel master, v1.5.4-pre.17, on Microsoft Windows [Version 10.0.17763.557], locale pl-PL)

[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[√] Android Studio (version 3.3)
[√] VS Code (version 1.35.1)
[√] Connected device (2 available)

I've confirmed this to be an issue in Observatory and DevTools. Haven't tested in Android Studio.

@bkonyi bkonyi added area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. vm-debugger labels Jun 19, 2019
@bkonyi bkonyi self-assigned this Jun 19, 2019
@bkonyi
Copy link
Contributor Author

bkonyi commented Jun 20, 2019

Having a hard time reducing the sample above to straight Dart code while maintaining the behavior we're seeing. Might be an issue specific to Flutter, but I'll have to investigate further.

@bkonyi
Copy link
Contributor Author

bkonyi commented Jun 27, 2019

It looks like the timer event is being dropped on the floor while the event handler is paused due to the breakpoint, which is why things will start working again when another asynchronous event is handled or the app is paused and resumed manually. This should be fixed in this CL.

@knopp
Copy link
Contributor

knopp commented Aug 18, 2022

@bkonyi, This is not a complete solution I'm afraid. Single invocation of

saved_notify_callback(Api::CastIsolate(this));

Will only result in one Dart_HandleMessage() call scheduled, which removes single message from the queue. However there might have been multiple messages added while callback was replaced.

We're having application deadlocking because it is missing Dart_PostCObject messages received while being paused on breakpoint.

If I modify the code to call saved_notify_callback(Api::CastIsolate(this)); for each message in the queue, the problem goes away.

@knopp
Copy link
Contributor

knopp commented Aug 18, 2022

For reference, here's the code:

sdk/runtime/vm/isolate.cc

Lines 3566 to 3575 in add88f2

// If any non-service messages came in, we need to notify the registered
// message notify callback to check for unhandled messages. Otherwise, events
// may be left unhandled until the next event comes in. See
// https://github.com/dart-lang/sdk/issues/37312.
if ((saved_notify_callback != nullptr) && handle_non_service_messages) {
saved_notify_callback(Api::CastIsolate(this));
}
set_message_notify_callback(saved_notify_callback);
Dart_ExitScope();
}

@knopp
Copy link
Contributor

knopp commented Aug 19, 2022

cc @rmacnak-google

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. vm-debugger
Projects
None yet
2 participants