]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: fix hang in workspaces
authorMichael Matloob <matloob@golang.org>
Tue, 23 Nov 2021 22:36:21 +0000 (17:36 -0500)
committerMichael Matloob <matloob@golang.org>
Wed, 8 Dec 2021 17:48:45 +0000 (17:48 +0000)
golang.org/cl/365234 incorrectly had pruningForGoVersion always return
workspace pruning instead of just returning workspace pruning at the top
level, which broke the proper determination of pruning for dependency
packages. Fix that code, and also fix a hang that resulted because the
module loading code keeps loading dependencies until it reaches a pruned
module or an unpruned module it already saw, so it could get stuck in a
cycle.

Change-Id: I8911f7d83aaee5870c43ef0355abbd439f15d4f7
Reviewed-on: https://go-review.googlesource.com/c/go/+/366775
Trust: Michael Matloob <matloob@golang.org>
Run-TryBot: Michael Matloob <matloob@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/go/internal/modload/init.go
src/cmd/go/internal/modload/modfile.go
src/cmd/go/testdata/script/work_regression_hang.txt [new file with mode: 0644]

index 854c17d7768abce19dba7c616496db884062f50a..df083e7fcca05475be6b676a767022f1aeca5b86 100644 (file)
@@ -694,7 +694,11 @@ func LoadModFile(ctx context.Context) *Requirements {
                MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, "", nil)
                goVersion := LatestGoVersion()
                rawGoVersion.Store(mainModule, goVersion)
-               requirements = newRequirements(pruningForGoVersion(goVersion), nil, nil)
+               pruning := pruningForGoVersion(goVersion)
+               if inWorkspaceMode() {
+                       pruning = workspace
+               }
+               requirements = newRequirements(pruning, nil, nil)
                return requirements
        }
 
index 7cc2272ea03cb4ffdb88c786d0e4d7a347648883..40e6ed787da8b763becca345c3030206395b3854 100644 (file)
@@ -124,9 +124,6 @@ const (
 )
 
 func pruningForGoVersion(goVersion string) modPruning {
-       if inWorkspaceMode() {
-               return workspace
-       }
        if semver.Compare("v"+goVersion, ExplicitIndirectVersionV) < 0 {
                // The go.mod file does not duplicate relevant information about transitive
                // dependencies, so they cannot be pruned out.
diff --git a/src/cmd/go/testdata/script/work_regression_hang.txt b/src/cmd/go/testdata/script/work_regression_hang.txt
new file mode 100644 (file)
index 0000000..a7661b6
--- /dev/null
@@ -0,0 +1,71 @@
+# This test makes checks against a regression of a bug in the Go command
+# where the module loader hung forever because all main module dependencies
+# kept workspace pruning instead of adopting the pruning in their go.mod
+# files, and the loader kept adding dependencies on the queue until they
+# were either pruned or unpruned, never breaking a module dependency cycle.
+#
+# This is the module graph in the test:
+#
+#                               /-------------------------\
+#                              |                          |
+#                              V                          |
+#  example.com/a -> example.com/b v1.0.0 -> example.com/c v1.1.0
+
+go list -m -f '{{.Version}}' example.com/c
+
+-- go.work --
+go 1.16
+
+use (
+       ./a
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+
+require example.com/b v1.0.0
+
+replace example.com/b v1.0.0 => ../b
+replace example.com/c v1.0.0 => ../c
+-- a/foo.go --
+package main
+
+import "example.com/b"
+
+func main() {
+       b.B()
+}
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+
+require example.com/c v1.0.0
+-- b/b.go --
+package b
+
+func B() {
+}
+-- b/cmd/main.go --
+package main
+
+import "example.com/c"
+
+func main() {
+       c.C()
+}
+-- c/go.mod --
+module example.com/c
+
+go 1.18
+
+require example.com/b v1.0.0
+-- c/c.go --
+package c
+
+import "example.com/b"
+
+func C() {
+       b.B()
+}
\ No newline at end of file