Skip to content

cmd/go: get and build can interact badly on case-insensitive but case-preserving file systems #20264

Closed
@josharian

Description

@josharian

Reproduce, using stock macOS filesystem, which is case-insensitive but case-preserving:

$ go get -d github.com/0x263b/Porygon2
$ go build -toolexec="toolstash -cmp" -a -o /dev/null github.com/0x263b/...

Result: Rare object file mismatches in which only a few bytes differ. Even rarer build failures in which we emit corrupt object files.

The reason is that go get downloads the code into $GOPATH/src/github.com/0x263b/Porygon2. go build then walks $GOPATH/src/github.com/0x263b, and adds the import paths corresponding to the directory names it sees, e.g. github.com/0x263b/Porygon2/web; note the capital P. Then it reads the import paths found in the code, which are lower case, and adds those import paths, including github.com/0x263b/porygon2/web; lower case p.

There's a check in PackagesForBuild for this exact scenario, aptly described in a comment:

	// Check for duplicate loads of the same package.
	// That should be impossible, but if it does happen then
	// we end up trying to build the same package twice,
	// usually in parallel overwriting the same files,
	// which doesn't work very well.

However, that check is case-sensitive, so this package sneaks past the check. Making the check do a strings.ToLower on the package import paths catches it:

internal error: duplicate loads of github.com/0x263b/porygon2
internal error: duplicate loads of github.com/0x263b/porygon2/web

This problem is not theoretical; I just wasted four hours tracking it down, starting from non-deterministic build failures.

This seems like a can of worms, and I don't know what the right fix is, but I think we should do something. Input requested.

cc @rsc @bradfitz @shurcooL

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions