Skip to content

Debugger pauses on exception that will be caught #2063

Closed

Description

@Fordevind

Have this problem with handling exceptions. I'm using Http package by Dart team. No such problem in Android Studio.
Снимок

Activity

  1. DanTup commented on Oct 22, 2019

    @DanTup
    Member

    @zichangg any thoughts on this? It sounds a bit like dart-lang/sdk#37645, however in this code it seems like the VM should be able to tell this exception will be caught (there's a catch block at the same level and the future is awaited). The settings are set to only break on uncaught exceptions (seen in the bottom left).

  2. changed the title [-]VS Code doesn't catched SocketException[/-] [+]Debugger pauses on exception that will be caught[/+] on Oct 22, 2019
  3. zichangg commented on Oct 22, 2019

    @zichangg

    From the screen shot, I didn't see anything goes wrong. The stack is not truncated from the screen shot. So that should be an caught exception.

    @Fordevind Can you do a dart --version? Is this a regression or new issue? It will be great if you have a reproduction instruction.

  4. Fordevind commented on Oct 23, 2019

    @Fordevind
    Author

    @zichangg
    Dart VM version: 2.5.0 (Fri Sep 6 20:10:36 2019 +0200) on "windows_x64"
    Issue appeared after upgrade from Flutter 1.5.4 to 1.9.1.

    Steps to reproduce:

    1. Turn off HTTP server at target url
    2. Execute this function:
    import 'package:http/http.dart' as http;
    
    void auth() async {
        try {
          await http.post(url, body: {'hello' : 'hello'}).timeout(Duration(seconds: 10));
        }
        catch (e) {
          print(e.toString());
        }
      }
    
  5. DanTup commented on Oct 23, 2019

    @DanTup
    Member

    From the screen shot, I didn't see anything goes wrong.

    The debugger has paused on the exception, but it's set to only pause on uncaught exceptions (shown in the tickboxes in the bottom left of the screenshot).

  6. zichangg commented on Oct 23, 2019

    @zichangg

    Thanks! I'll take a look later.
    Well, what I mean is code itself looks right. ^_^

  7. zichangg commented on Oct 23, 2019

    @zichangg

    @DanTup Can you assign me this issue, if possible? I need to finish some other issues first.

  8. DanTup commented on Oct 23, 2019

    @DanTup
    Member

    Well, what I mean is code itself looks right. ^_^

    Oh, I see! 😄

    Can you assign me this issue, if possible?

    Apparently I can! I thought I'd have to add you to the repo first, but apparently not :-)

  9. zichangg commented on Nov 1, 2019

    @zichangg

    I suspect that the exception is the first one showed in dart-lang/sdk#37645 (comment). Because in VScode, libraries are non-debuggable so it doesn't show at where it happens. Instead, it marked line in your _auth(). You can look at comments on #37645.

    @Fordevind Can you check whether 'debugSdkLibraries' and 'debugExternalLibraries' are set to 'false' in your setting?

  10. Fordevind commented on Nov 1, 2019

    @Fordevind
    Author

    @zichangg It was set to 'false'
    Снимок1

  11. zichangg commented on Nov 1, 2019

    @zichangg

    Thanks!

    An unhandled exception was thrown inside libraries. Since 'debugSdkLibraries' and 'debugExternalLibraries' are 'false'. It didn't pause until program reaches the user written code.
    Here is what @DanTup explained in the other thread.

    it would only break once the exception made it up to the user code. This is somewhat what we achieve in VS Code today by automatically jumping up the call stack to the users code

    Why exception is considered as 'unhandled' even if you put 'try catch' block?

    VM determines whether an exception is handled or not by checking current stack trace. But when thing happens asynchronously, stack may be out of date and not contains frame that has handler.

  12. DanTup commented on Nov 4, 2019

    @DanTup
    Member

    @zichangg I'm not sure I understand. At the location where the debugger is breaking, isn't the try/catch visible in the stack? This seems very confusing to users (it keeps coming up - another one at #2085 this weekend), is there anything that can be done?

    We default to having SDK libraries as non-debuggable as most users seem to prefer to treat the SDK as a black box and not have to keep stepping in/out of it (we used to have those settings enabled by default, but when we added an option we prompted users, and almost all picked to debug "just my code" so that became the new default).

  13. zichangg commented on Nov 4, 2019

    @zichangg

    At the location where the debugger is breaking, isn't the try/catch visible in the stack?

    It is visible. But it is not the same as the stack when exception is thrown.
    I suspect that when exception was thrown inside the external library, the stack doesn't contain handler frame. So VM treat it as unhandled.
    Due to 'non-debuggable libraries',correct me if I'm wrong, VScode resumes pausing until it reaches user-written code. The stack changes as exception propagates. It ends up pausing on a different place and displaying current stack(not the stack when exception is thrown).

  14. DanTup commented on Nov 5, 2019

    @DanTup
    Member

    Due to 'non-debuggable libraries',correct me if I'm wrong, VScode resumes pausing until it reaches user-written code.

    Sorry, my previous comment was a little misleading. The VM is still breaking in the location of the exception, but VS Code is choosing to display the first stack frame of user code (if you look at the call stack, you'll see it still goes all the way up to where the exception is thrown - that is where the VM is paused).

    So if we were to ignore the VS Code behaviour of jumping up the stack (this is only cosmetic, to put the user at their own code - we're not telling the VM to do anything) then we are essentially paused at the location of the original exception.

    So I think this may be the same thing described at the end of the comment here:

    dart-lang/sdk#37645 (comment)

    which was that the SDK/libraries are using .catchError() and not try/catch themselves?

    I'll try and do some more testing of this later today and see exactly where the exception occurs and what the stack looks like.

  15. DanTup commented on Nov 5, 2019

    @DanTup
    Member

    Ok, seems like this is actually being trigged by having .timeout() on the end (even if the timeout does not fire).

    I can repro with this code:

    import 'package:http/http.dart' as http;
    
    Future<void> main(List<String> arguments) async {
      try {
        await http.post('http://127.0.0.1:9999/').timeout(Duration(seconds: 100));
      } catch (e) {
        print('Error occured :( $e');
      }
      print('Done!');
    }

    In this case, the exception is considered unhandled and the debugger breaks (the timeout did not trigger - the exception occurred immediately, though presumably will have been passed through the timeout function).

    If I delete .timeout(Duration(seconds: 100)) from the end, then the debugger does not break.

    I think this is the implementation of the timeout:

    https://github.com/dart-lang/sdk/blob/4ebc1e3fe7e1cd3d000ec2c371671a51149a3a5c/sdk/lib/async/future_impl.dart#L753

    It uses a class called _Future which seems to work a little like Completer, however when I tried to reproduce the issue using a Complete that completes with an error, I could not.

    @zichangg does this make any sense to you?

  16. zichangg commented on Nov 8, 2019

    @zichangg

    Sorry for the late reply.

    The VM is still breaking in the location of the exception, but VS Code is choosing to display the first stack frame of user code (if you look at the call stack, you'll see it still goes all the way up to where the exception is thrown - that is where the VM is paused).

    Get it!

    I run the sample with "--trace-debugger-stacktrace". This is likely to be a bug in debugger. Stack trace was truncated.

    Stack(from top to bot):

    CollectAwaiterReturnStackTrace: visiting frame:
    [exit : sp(0) fp(0x7fa1bfdfd2e8) pc(0)]

    CollectAwaiterReturnStackTrace: visiting frame:
    [dart : sp(0x7fa1bfdfd2f8) fp(0x7fa1bfdfd3a0) pc(0x7fa1c02fc745) package:http/src/io_client.dart_IOClient_send__async_op ]
    Found saved current ctx at index -5
    Using saved context: Context num_variables: 3 parent:{ Context num_variables: 12 }
    Line number: 33

    CollectAwaiterReturnStackTrace: visiting frame:
    [dart : sp(0x7fa1bfdfd3b0) fp(0x7fa1bfdfd3f0) pc(0x7fa1bd722c40) dart:core__Closure@0150898_call ]
    Found saved current ctx at index 0
    Using saved context: Context: null
    Line number: -1

    CollectAwaiterReturnStackTrace: visiting frame:
    [dart : sp(0x7fa1bfdfd400) fp(0x7fa1bfdfd450) pc(0x7fa1bd60a280) dart:async_::_asyncErrorWrapperHelper@9048458 ]

    CollectAwaiterReturnStackTrace: visiting awaiter return closures:
    package:http/src/base_client.dart_BaseClient__sendUnstreamed@23340606__async_op

    CollectAwaiterReturnStackTrace: visiting awaiter return closures:
    package:http/http.dart_::__withClient@20447473__async_op

    It doesn't contain frame that has user-written try catch block.
    I have other prioritized issue to work on, so I'll get back to this later.

  17. DanTup commented on Nov 11, 2019

    @DanTup
    Member

    Ok, great - let me know if you need anything more info or someone to test a fix :-)

  18. HerrNiklasRaab commented on Apr 26, 2020

    @HerrNiklasRaab

    Is this issue specific to .timeout or general?

    Just wondering because I am also getting something similiar:
    image

  19. DanTup commented on Apr 27, 2020

    @DanTup
    Member

    I don't think it was specific to .timeout(), I think it was related to the function taking a future, but then using a completer to products its own future that succeeds/fails. I think the initial future throwing was considered unhandled, even though the only place waiting on its result was handling it.

    @zichangg likely understands this better though (I'm not sure whether the original issue was resolved or not).

  20. added this to the On Deck milestone on Oct 1, 2020
  21. DanTup commented on Jan 12, 2021

    @DanTup
    Member

    Closing this as a dupe of dart-lang/sdk#37953, since the fix will need to be done there (and would apply automatically in VS Code).

  22. removed this from the On Deck milestone on Jan 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions