aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/csource/generated.go
diff options
context:
space:
mode:
authorMark Johnston <markjdb@gmail.com>2022-06-13 13:55:38 -0400
committerDmitry Vyukov <dvyukov@google.com>2022-06-17 07:59:41 +0200
commitcb58b3b231a677b1a6c89cd2af59e4fab10f9144 (patch)
tree6c46ec03c5c6f148b569e9083e8c704796c8be6b /pkg/csource/generated.go
parent1719ee24e741afb177677e9644f1c74aef1060fb (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.go32
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