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

Bug Causing Dart.exe to Eat Up All Available Memory. #56355

Closed
aalharbi169638 opened this issue Jul 31, 2024 · 15 comments
Closed

Bug Causing Dart.exe to Eat Up All Available Memory. #56355

aalharbi169638 opened this issue Jul 31, 2024 · 15 comments
Assignees
Labels
analyzer-stability area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. fe-analyzer-shared-parser-recovery Issues with the shared parser's handling of incorrect code P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) type-performance Issue relates to performance or code size

Comments

@aalharbi169638
Copy link

There's a reproducible bug that causes dart.exe to take up all available RAM in my device; I was able to reproduce this bug multiple times. I couldn't find any good solution online though.

the only packaged I used for this project is the http package published by dart.dev.

The issue occurs exactly when i type "http.Response response = http.g" inside the Future method to use the get method for that package.

Thank you,

code causing issue
RAM taken
notification error

@dart-github-bot
Copy link
Collaborator

Summary: The user is experiencing a memory leak in dart.exe when using the http package's get method within a Future function. This issue consistently occurs when attempting to assign the result of http.get to a http.Response variable.

@dart-github-bot dart-github-bot added area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) labels Jul 31, 2024
@aalharbi169638 aalharbi169638 changed the title Reproducible Bug Causing Dart.exe to Eat Up All Available Memory. Bug Causing Dart.exe to Eat Up All Available Memory. Jul 31, 2024
@a-siva a-siva added area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. and removed area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. labels Jul 31, 2024
@aam
Copy link
Contributor

aam commented Jul 31, 2024

It reproduces locally on gWindows with following log:

Dart analysis issue

Out of Memory

Version information

  • Dart SDK 3.5.0-176.0.dev
  • Dart IntelliJ 212.5744
  • Android Studio Chipmunk | 2021.2.1 Patch 2
  • Windows 10 10.0

Details

Out of Memory

#0      List._growToNextCapacity (dart:core-patch/growable_array.dart:397:5)
#1      AstNodeExtension.allTokens (package:analyzer/src/utilities/extensions/ast.dart:14:14)
#2      AstNodeExtension.commentTokenCovering (package:analyzer/src/utilities/extensions/ast.dart:29:23)
#3      PostfixCompletionProcessor.isApplicable (package:analysis_server/src/services/completion/postfix/postfix_completion.dart:441:16)
#4      EditIsPostfixCompletionApplicableHandler.handle (package:analysis_server/src/handler/legacy/edit_is_postfix_completion_applicable.dart:37:31)
#5      _rootRunUnary (dart:async/zone.dart:1407:47)
#6      _FutureListener.handleValue (dart:async/future_impl.dart:163:18)
#7      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:861:45)
#8      Future._propagateToListeners (dart:async/future_impl.dart:890:13)
#9      Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:736:7)
#10     _rootRun (dart:async/zone.dart:1399:13)
#11     _CustomZone.runGuarded (dart:async/zone.dart:1209:7)
#12     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1249:23)
#13     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
#14     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:405:11)
#15     _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

Debug log

1722457584164 => {"id":"303","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457584440 => {"id":"304","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457584440 => {"id":"305","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457584683 => {"id":"306","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457584683 => {"id":"307","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457584941 => {"id":"308","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457584941 => {"id":"309","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457585212 => {"id":"310","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457585212 => {"id":"311","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457585486 => {"id":"312","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457585486 => {"id":"313","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457585749 => {"id":"314","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457585749 => {"id":"315","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457586021 => {"id":"316","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457586021 => {"id":"317","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457591030 => {"id":"318","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457596366 => {"id":"319","method":"edit.getAssists","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"length":0},"clientRequestTime":1722457596366}
1722457601100 => {"id":"320","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457601100 => {"id":"321","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457601364 => {"id":"322","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457601364 => {"id":"323","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457601621 => {"id":"324","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457601621 => {"id":"325","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457601830 => {"id":"326","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457601830 => {"id":"327","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457602139 => {"id":"328","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457602139 => {"id":"329","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457602733 => {"id":"330","method":"analysis.updateContent","params":{"files":{"C:\\src\\d1\\sdk\\b56355.dart":{"type":"add","content":"import 'package:http/http.dart' as http;\n\nclass CurrencyExc...
1722457602733 => {"id":"331","method":"completion.getSuggestions2","params":{"file":"C:\\src\\d1\\sdk\\b56355.dart","offset":206,"maxResults":100,"completionCaseMatchingMode":"FIRST_CHAR","completionM...
1722457607445 <= {"id":"110","error":{"code":"SERVER_ERROR","message":"Out of Memory","stackTrace":"#0      List._growToNextCapacity (dart:core-patch/growable_array.dart:397:5)\n#1      AstNodeExtensi...

@lrhn lrhn removed the triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. label Jul 31, 2024
@bwilkerson bwilkerson added type-performance Issue relates to performance or code size P2 A bug or feature request we're likely to work on labels Aug 1, 2024
@aam
Copy link
Contributor

aam commented Aug 2, 2024

cc @scheglov

@mraleph
Copy link
Member

mraleph commented Oct 3, 2024

Analyzer eating through all available memory should not be P2. Can somebody look at this?

@mraleph
Copy link
Member

mraleph commented Oct 3, 2024

@aam can you still reliable reproduce this? I have tried different variants of

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

class CurrencyExchanger {
  final Uri? currencyURL;

  const CurrencyExchanger({required this.currencyURL});

  Future getData(){
    http.Response response = http.G
  }
}

and none of them cause OOM.

@aam
Copy link
Contributor

aam commented Oct 3, 2024

@mraleph wrote

can you still reliable reproduce this? I have tried different variants of

I think so, yes. I have

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

class CurrencyExchanger {
  final Uri? currencyURL;

  const CurrencyExchanger({required this.currencyURL});

  Future getData() {
    http.Response response = http
  }
}

in the root of dart sdk repo that I go back and forth adding/removing characters after " = http".

The runaway growth starts at second 44 in the video below
https://github.com/user-attachments/assets/886a52c6-5925-4373-b430-ba90cdcb3cf2

That is on

  • Dart SDK 3.6.0-149.3.beta
  • Dart IntelliJ 212.5744
  • Android Studio Chipmunk | 2021.2.1 Patch 2
  • Windows 10 10.0

@mraleph
Copy link
Member

mraleph commented Oct 3, 2024

I still can't reproduce OOM myself but what I managed to reproduce is analyzer getting stuck. If I start with

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

class CurrencyExchanger {
  final Uri? currencyURL;

  const CurrencyExchanger({required this.currencyURL});

  Future get() {
    http.Response response = http
  }
}

and then I type Data after get then analyzer stops responding. It seems that import might not even be necessary to reproduce this.

@scheglov does analyzer team have some easy way of replaying reproductions like this?

@scheglov
Copy link
Contributor

scheglov commented Oct 3, 2024

I don't think we have an existing way to replay Analysis Server protocol logs.

@scheglov
Copy link
Contributor

scheglov commented Oct 3, 2024

I can reproduce it manually though, and see in Observatory where it goes into a cycle, or at least uses too much CPU.

@bwilkerson
Copy link
Member

I don't think we have an existing way to replay Analysis Server protocol logs.

I don't think we do either, but we can write a test that sends repeated 'overlay' requests to the server simulating what happens as the user types.

@scheglov
Copy link
Contributor

scheglov commented Oct 3, 2024

Can be reduced to requesting completion at ^.

void get^() {
  http.Response response = http
}

So far it seems that linking of tokens via previous has a cycle.

@scheglov
Copy link
Contributor

scheglov commented Oct 3, 2024

It looks that there is an issue with parser recovery.
I enhanced the printer for AST and tokens in the analyzer, and see this for the code above.
Note previousX - these are references to tokens that must have been already seen, but actually we don't.
And T8 T9 T10 T11 form a cycle via previous.

FunctionDeclaration
  returnType: NamedType
    name: T0 void @0
      next: T1 |get|
  name: T1 get @5
    previous: T0 |void|
    next: T2 |(|
  functionExpression: FunctionExpression
    parameters: FormalParameterList
      leftParenthesis: T2 ( @8
        previous: T1 |get|
        next: T3 |)|
      rightParenthesis: T3 ) @9
        previous: T2 |(|
        next: T4 |{|
    body: BlockFunctionBody
      block: Block
        leftBracket: T4 { @11
          previous: T3 |)|
          next: T5 |http|
        statements
          ExpressionStatement
            expression: PrefixedIdentifier
              prefix: SimpleIdentifier
                token: T5 http @15
                  previous: T4 |{|
                  next: T6 |.|
              period: T6 . @19
                previous: T5 |http|
                next: T7 |Response|
              identifier: SimpleIdentifier
                token: T7 Response @20
                  previous: T6 |.|
                  next: T8 |response|
            semicolon: T9 ; @45 <synthetic>
              previousX: T10 http @40
                previousX: T11 = @38
                  previous: T8 |response|
                  next: T10 |http|
                next: T9 |;|
              next: T8 |response|
          ExpressionStatement
            expression: SimpleIdentifier
              token: T8 response @29
                previous: T9 |;|
                next: T12 |;|
            semicolon: T12 ; @45 <synthetic>
              previous: T8 |response|
              next: T13 |}|
        rightBracket: T13 } @45
          previous: T12 |;|
          next: T14 ||

@bwilkerson bwilkerson added the fe-analyzer-shared-parser-recovery Issues with the shared parser's handling of incorrect code label Oct 3, 2024
copybara-service bot pushed a commit that referenced this issue Oct 3, 2024
Bug: #56355
Change-Id: I0cd58070853cfe0fa59788b3ed4586fc156e27d3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388054
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
@mraleph
Copy link
Member

mraleph commented Oct 4, 2024

cc @jensjoha for recovery issues.

@jensjoha
Copy link
Contributor

This is not the parser.
The analyzer rewrites here:

parser.rewriter.insertToken(semicolon, awaitToken);

even while we're parsing.

All the rewrites happening on

void get() {
  http.Response response = http
}

in test_recovery_body_issue56355 are:

From Parser.ensureSemicolon via Parser.parseVariablesDeclarationRest
Before: void get ( ) { http . Response response = http }
After: void get ( ) { http . Response response = http ; }

From AstBuilder.endVariablesDeclaration via Parser.parseVariablesDeclarationRest
Before: void get ( ) { http . Response response = http ; }
After: void get ( ) { http . Response (bad previous here) response }

From Parser.ensureSemicolon via Parser.parseExpressionStatement
Before: void get ( ) { http . Response (bad previous here) response }
After: void get ( ) { http . Response (bad previous here) response ; }

@scheglov scheglov self-assigned this Oct 29, 2024
@scheglov
Copy link
Contributor

copybara-service bot pushed a commit that referenced this issue Oct 29, 2024
Bug: #56355
Change-Id: I1ee7f837dc8beed9bb2ed1f27c45108345e7cceb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392460
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer-stability area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. fe-analyzer-shared-parser-recovery Issues with the shared parser's handling of incorrect code P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) type-performance Issue relates to performance or code size
Projects
None yet
Development

No branches or pull requests

10 participants