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

OutOfMemoryError caused by infinite loop inside StateNode.visitNodeTreeBottomUp() #13366

Closed
ignacio-alvarez opened this issue Mar 25, 2022 · 5 comments · Fixed by #13370
Closed

Comments

@ignacio-alvarez
Copy link

Description of the bug

For several weeks we had frequent application crashes caused by an OutOfMemoryError. It appears it is being caused by an infinite loop inside StateNode.visitNodeTreeBottomUp():

void visitNodeTreeBottomUp(Consumer<StateNode> visitor) {

The infinite loop happens because the implementation depends on a child node pointing to the correct parent, line 714:

previousParent = current.getParent();

But what happens if a child node points to a different parent? What happens if getParent() is null? If that happens to the first child node, it enters into an infinite loop because the condition if (current == previousParent) never becomes true, and the loop alternates between removing the child node and adding it again infinitely.

The OutOfMemoryError occurs because the infinite loop is triggered during an onDetach() event, and visitor.accept() expands its internal ArrayList until it runs out of memory.

This error is difficult to reproduce because it is actually an implementation flaw that is triggered by other random hidden bugs, that sometimes cause a child node to not point to its parent. We had crashes as frequently as every few hours, and sometimes we went days without triggering it.

We fixed the problem by replacing visitNodeTreeBottomUp() with a recursive function so that it doesn't depend on getParent() anymore. We've read why there are no recursive functions in StateNode, but we have no need for nesting thousands of nodes, and if we do, we can just increase the thread stack size:
#252

We wanted to report this issue in case there are other users having the same problem.

Thank you.

Expected behavior

Application shouldn't enter into an infinite loop and crash with an OutOfMemoryError.

Minimal reproducible example

This bug is difficult to reproduce, because it depends on other bugs that are triggered randomly. We had crashes as frequently as every few hours, and sometimes we went days without triggering it.

Versions

  • Vaadin / Flow version: 23.0.0
  • Java version: International Business Machines Corporation 11.0.12
  • OS version: amd64 Linux 5.15.23-76051523-generic
  • Browser version (if applicable): Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/98.0
  • Application Server (if applicable):
  • IDE (if applicable):
@knoobie
Copy link
Contributor

knoobie commented Mar 25, 2022

This feels kinda related to another refactoring I've observed in the past #12665

caalador added a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366
@caalador caalador self-assigned this Mar 28, 2022
mcollovati pushed a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366
vaadin-bot pushed a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366
vaadin-bot pushed a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366
vaadin-bot pushed a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366
vaadin-bot pushed a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366
vaadin-bot added a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366

Co-authored-by: caalador <[email protected]>
vaadin-bot added a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366

Co-authored-by: caalador <[email protected]>
vaadin-bot added a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366

Co-authored-by: caalador <[email protected]>
mcollovati pushed a commit that referenced this issue Mar 28, 2022
Do not constantly add children
of a node that has already had
all children added once.

Fixes #13366

Co-authored-by: caalador <[email protected]>
@ignacio-alvarez
Copy link
Author

@caalador Just an observation, there should be a childrenAdded.add(this) after line 708, to prevent the root node from being iterated twice.

@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 14.8.7.

@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 22.0.12.

@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 23.0.4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants