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

Circular dependencies in SSR not detected and causes indefinite hang #2491

Closed
3 tasks done
antimatter15 opened this issue Mar 13, 2021 · 1 comment · Fixed by #3950
Closed
3 tasks done

Circular dependencies in SSR not detected and causes indefinite hang #2491

antimatter15 opened this issue Mar 13, 2021 · 1 comment · Fixed by #3950

Comments

@antimatter15
Copy link

antimatter15 commented Mar 13, 2021

⚠️ IMPORTANT ⚠️ Please do not ignore this template. If you do, your issue will be closed immediately.

Describe the bug

Let's say we have three files: A, B, and C, where A is the entry point. B and C cyclically depend on each other. A depends on both B and C. In this situation, Vite will not detect the cyclic dependency and simply hang indefinitely.

Reproduction

Create the following 3 files inside of the src/pages directory of the ssr-react playground. Attempt to load the /A page, and notice that it hangs forever and the logs are empty.

// A.jsx
import { addFour } from './B'
import { addTwo } from './C'

export default function Main(){
    return addFour(addTwo(1))
}

// B.js
import { addTwo } from './C'
export function addOne(x){
    return x + 1
}
export function addFour(x){
    return addTwo(addTwo(x))
}

// C.js
import { addOne } from './A'
export function addTwo(x){
    return addOne(addOne(x))
}

Explanation

This bug happens because ssrLoadModule first gets called with A, the entry point. Within instantiateModule, it then tries to load the dependencies B and C in parallel, and caches their promises in the pendingModules map.

When instantiateModule finally runs on B, it blocks until ssrLoadModule completes for its sole dependency: C. When ssrLoadModule is called, the urlStack only has [A, B] so it bypasses the circular dependency test. Since C is already in the pendingModules map, it returns the existing promise waiting for C to load.

Essentially this results in a state where A depends on B and C, while B and C both depend on each other. At this point ssrLoadModule will never complete.

System Info

  • vite version: 2.0.5
  • Operating System: macOS 11.2
  • Node version: 15.11
  • Package manager (npm/yarn/pnpm) and version: Yarn 1.22.10
@antimatter15 antimatter15 changed the title Circular dependencies in SSR sometimes not detected and causes indefinite hang Circular dependencies in SSR not detected and causes indefinite hang Mar 13, 2021
aral added a commit to small-tech/domain that referenced this issue Apr 28, 2021
@raythurnvoid
Copy link
Contributor

@fairbanksg I've improved your fix with another case:

A -> B means: B is imported by A and B has A in its stack
A ... B means: A is waiting for B to ssrLoadModule()

H -> [X] ... (Y)
H -> [X] -> (Y) ... {B}
H -> A -> {B} ... |M|
H -> A -> {B} -> |M| ... [X]

Deadlock description:
[X] is waiting for (Y) to resolve 
	which is waiting for {B} 
	which is waiting for |M|
	which is waiting for [X]

H is the first module in common by all modules

https://github.com/raythurnevoid/vite/commit/4bffced904bb04c32ae48084cbda1fb156e26e9e

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
4 participants