vlang

/

v Public
0 commits 39 issues 0 pull requests 0 contributors Discussions Projects CI

Windows: building a V project located directly under a drive root hangs forever (infinite loop in find_module_path) #3

Describe the bug

On Windows, compiling a V project that is located directly under a drive root (e.g. S:\vlang2) hangs forever (100% CPU on one core, memory slowly growing, no output). The same sources compile fine when the project is nested one level deeper (e.g. S:\repo\vlang).

This also makes make/makev.bat hang at the Compiling "./v_stage.exe" with "./v_win_bootstrap.exe" step when the checkout is at a drive root.

Reproduce

  1. Put a V checkout directly under a drive root, e.g. S:\v.
  2. From that directory, build the compiler:
    v -o vnew cmd/v
    
    Observed: hangs indefinitely. Building the same sources from a nested path (e.g. S:\some\dir\v) completes normally.Minimal trigger: the hang occurs while resolving the first cross-module import of cmd/v (import hash from cmd/v/v.v). A trivial single-file program (v run examples/hello_world.v) does not hang, because it has no such import.

Root cause

The infinite loop is in find_module_path() in vlib/v/builder/builder.v — the loop that anchors an importer to the outermost enclosing v.mod:

importer_vmod_folder = vmod_file_location.vmod_folder   // e.g. "S:\v"
for {
    parent := os.dir(importer_vmod_folder)              // os.dir("S:\v") -> "S:"
    if parent == importer_vmod_folder {
        break
    }
    parent_loc := mcache.get_by_folder(parent)          // get_by_folder("S:")
    if parent_loc.vmod_file == '' {
        break
    }
    importer_vmod_folder = parent_loc.vmod_folder        // -> back to "S:\v"
}

When the project sits at a drive root:

  • os.dir("S:\v") returns the bare drive "S:".
  • inside get_by_folder("S:"), os.real_path("S:") resolves a bare drive letter to that drive's current directory ("S:\v"), not the drive root.So importer_vmod_folder never advances past "S:\v", while the loop's progress guard compares the unresolved "S:" against "S:\v" — they differ textually, so it never breaks. The loop spins forever.At a nested path the parent (S:\repo) has no v.mod, so parent_loc.vmod_file == '' and the loop exits — which is why nesting the project avoids the bug.Confirmation of the OS-level behavior (run from S:\v):
    os.dir("S:\v")    => "S:"
    os.real_path("S:")  => "S:\v"     # bare drive letter -> drive's current dir
    os.real_path("S:\") => "S:\"
    

Suggested fix

Break the loop when resolving parent makes no upward progress:

parent_loc := mcache.get_by_folder(parent)
if parent_loc.vmod_file == '' {
    break
}
if parent_loc.vmod_folder == importer_vmod_folder {
    // no upward progress (e.g. a bare drive letter like `S:` resolves back
    // to the same folder on Windows); stop to avoid an infinite loop
    break
}
importer_vmod_folder = parent_loc.vmod_folder

With this guard, building cmd/v from a drive-root checkout completes normally (~27s in my test, vs. never), and the resulting compiler self-rebuilds at the drive root in ~6s.

Note: because make/makev.bat bootstrap the first stage from the pre-generated vc/v_win.c, the bootstrap step will keep hanging at a drive-root checkout until vlang/vc is regenerated with this fix.

Expected behavior

Building a V project located at a drive root on Windows should work the same as building it from a nested directory.

V version / Environment

  • V 0.5.1
  • OS: Windows 11 (x64)
    [!NOTE] You can use the 👍 reaction to increase the issue's priority for developers.Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.