diff options
| author | Mark Johnston <markjdb@gmail.com> | 2022-06-13 13:55:38 -0400 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2022-06-17 07:59:41 +0200 |
| commit | cb58b3b231a677b1a6c89cd2af59e4fab10f9144 (patch) | |
| tree | 6c46ec03c5c6f148b569e9083e8c704796c8be6b /pkg/csource/generated.go | |
| parent | 1719ee24e741afb177677e9644f1c74aef1060fb (diff) | |
executor: try harder to unlink files on FreeBSD
There is a BSD syscall, chflags(2), which lets one set various flags on
a file, including several that prevent unlinking. The use of this flag
can cause the executor to fail to clean up tmpdirs, which can lead to
spurious reports.
Thus, when unlinking fails, try again after clearing relevant flags. I
suspect this would be useful on other BSDs but I can't easily verify
that this change works there. It may eventually be worth having a
BSD-specific remove_dir() implementation.
Diffstat (limited to 'pkg/csource/generated.go')
| -rw-r--r-- | pkg/csource/generated.go | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go index 7e9c922b1..bfd60f23e 100644 --- a/pkg/csource/generated.go +++ b/pkg/csource/generated.go @@ -216,6 +216,18 @@ static void use_temporary_dir(void) #include <string.h> #include <sys/stat.h> #include <sys/types.h> + +#if GOOS_freebsd +static void reset_flags(const char* filename) +{ + struct stat st; + if (lstat(filename, &st)) + exitf("lstat(%s) failed", filename); + st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE); + if (lchflags(filename, st.st_flags)) + exitf("lchflags(%s) failed", filename); +} +#endif static void __attribute__((noinline)) remove_dir(const char* dir) { DIR* dp = opendir(dir); @@ -240,12 +252,28 @@ static void __attribute__((noinline)) remove_dir(const char* dir) remove_dir(filename); continue; } - if (unlink(filename)) + if (unlink(filename)) { +#if GOOS_freebsd + if (errno == EPERM) { + reset_flags(filename); + if (unlink(filename) == 0) + continue; + } +#endif exitf("unlink(%s) failed", filename); + } } closedir(dp); - if (rmdir(dir)) + while (rmdir(dir)) { +#if GOOS_freebsd + if (errno == EPERM) { + reset_flags(dir); + if (rmdir(dir) == 0) + break; + } +#endif exitf("rmdir(%s) failed", dir); + } } #endif #endif |
