Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
compilepkg: fix race when run without sandbox
On platforms without sandbox execution support such as Windows, multiple go_test targets declared in the same package would cause a race condition. ``` [ go_library( name = "same_package_{}".format(i), srcs = ["same_package.go"], importpath = "github.com/bazelbuild/rules_go/tests/core/go_test/same_package_{}".format(i), x_defs = { "name": "{}".format(i), }, ) for i in range(1, 80) ] [ go_test( name = "same_package_{}_test".format(i), srcs = ["same_package_test.go"], embed = [":same_package_{}".format(i)], ) for i in range(1, 80) ] ``` For each of go_test targets, there would be internal archive and external archive that needs to compile from source files. However, due to testfilter, external archive would end up without any Go source and thus compilepkg needs to generate a dummy source file `_empty.go` to trick 'go tool compile'. This `_empty.go` file is generated in the output path of the Bazel package thus multiple go_test targets in the same package would generate this file using the same path. On a sandbox supported platform, this is not a problem as the full path is prefixed with the sandbox root dir. However, without sandbox, the full path is the same for each go_test's external archive compilation, leading to a race condition where multiple compilations running in parallel would compete to create/delete the same file. Fix this by using the unique importPath to create a directory to store the _empty.go file. This would effectively give each go_test compilation it's own _empty.go file in non-sandbox environment. Worth to note that in current solution, we still have yet to solve problem when 'importPath' is not provided. For example, in a setup like this where `go_library` does not exist, `importPath` will be blank and thus causes similar issues on non-sandbox platforms. ``` [ go_test( name = "same_package_{}_test".format(i), srcs = ["same_package_test.go"], ) for i in range(1, 80) ] ``` Although this is a valid use case, we recommend avoid setting up tests this way. Instead, you could setup a single go_test target with multiple shards to achieve similar result: ``` go_test( name = "same_package_{}_test".format(i), srcs = ["same_package_test.go"], shard_count = 80, ) ``` For more information, please review Bazel Test Sharding documentation(1) (1): https://docs.bazel.build/versions/main/test-encyclopedia.html#test-sharding
- Loading branch information