From d6baa3cab0271ec7c2a92f7d3f51dc7242330292 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Fri, 26 Jan 2024 19:22:35 +0400 Subject: [PATCH] fix: stop running tests that exec sh scripts in parallel (#11834) Ok, so my last attempt at a fix here failed https://github.com/coder/coder/actions/runs/7666229961/job/20893608286 I have a new theory: it's not the `terraform` binary that's busy, it's actually `fake_cancel.sh` and it gets marked busy when we `exec` it from the script we write. Use of `exec` also replaces the executing code in place, rather than starting a new process/shell, so that's why the error we get says `terraform` is busy. --- provisioner/terraform/provision_test.go | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/provisioner/terraform/provision_test.go b/provisioner/terraform/provision_test.go index 85868fe611..1395877b18 100644 --- a/provisioner/terraform/provision_test.go +++ b/provisioner/terraform/provision_test.go @@ -14,7 +14,6 @@ import ( "runtime" "sort" "strings" - "syscall" "testing" "time" @@ -126,8 +125,10 @@ func sendApply(sess proto.DRPCProvisioner_SessionClient, transition proto.Worksp }}}) } +// below we exec fake_cancel.sh, which causes the kernel to execute it, and if more than +// one process tries to do this simultaneously, it can cause "text file busy" +// nolint: paralleltest func TestProvision_Cancel(t *testing.T) { - t.Parallel() if runtime.GOOS == "windows" { t.Skip("This test uses interrupts and is not supported on Windows") } @@ -158,24 +159,16 @@ func TestProvision_Cancel(t *testing.T) { } for _, tt := range tests { tt := tt + // below we exec fake_cancel.sh, which causes the kernel to execute it, and if more than + // one process tries to do this, it can cause "text file busy" + // nolint: paralleltest t.Run(tt.name, func(t *testing.T) { - t.Parallel() - dir := t.TempDir() binPath := filepath.Join(dir, "terraform") // Example: exec /path/to/terrafork_fake_cancel.sh 1.2.1 apply "$@" content := fmt.Sprintf("#!/bin/sh\nexec %q %s %s \"$@\"\n", fakeBin, terraform.TerraformVersion.String(), tt.mode) - - // golang's standard OS library can sometimes leave the file descriptor open even after - // "Closing" the file (which can then lead to a "text file busy" error, so we bypass this - // and use syscall directly). - fd, err := syscall.Open(binPath, syscall.O_WRONLY|syscall.O_CREAT, 0o755) - require.NoError(t, err) - n, err := syscall.Write(fd, []byte(content)) - require.NoError(t, err) - require.Equal(t, len(content), n) - err = syscall.Close(fd) + err := os.WriteFile(binPath, []byte(content), 0o755) //#nosec require.NoError(t, err) t.Logf("wrote fake terraform script to %s", binPath) @@ -228,8 +221,10 @@ func TestProvision_Cancel(t *testing.T) { } } +// below we exec fake_cancel_hang.sh, which causes the kernel to execute it, and if more than +// one process tries to do this, it can cause "text file busy" +// nolint: paralleltest func TestProvision_CancelTimeout(t *testing.T) { - t.Parallel() if runtime.GOOS == "windows" { t.Skip("This test uses interrupts and is not supported on Windows") }