aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJade Lovelace <lix@jade.fyi>2024-08-10 01:10:35 -0700
committerJade Lovelace <lix@jade.fyi>2024-08-10 16:11:58 -0700
commitb9ed79c99a35f91e438edd96eb37fe4f43002e70 (patch)
tree9869634c2b1a03cc7c0170de7a959c5e8e48dba4
parentb15d5cc6ee566127a634fcad74fef7e251f17878 (diff)
libutil: deal with Linux systems that do not implement close_range
Seems a little bit Rich that musl does not implement close_range because they suspect that the system call itself is a bad idea, so they uhhhh are considering not implementing a wrapper. Let's just fix the problem at hand by writing our own wrapper. Change-Id: I1f8e5858e4561d58a5450503d9c4585aded2b216
-rw-r--r--meson.build5
-rw-r--r--src/libutil/file-descriptor.cc16
2 files changed, 19 insertions, 2 deletions
diff --git a/meson.build b/meson.build
index 4e2f713ce..41bfe6722 100644
--- a/meson.build
+++ b/meson.build
@@ -417,6 +417,11 @@ check_funcs = [
'strsignal',
'sysconf',
]
+if target_machine.kernel() in ['linux', 'freebsd']
+ # musl does not have close_range as of 2024-08-10
+ # patch: https://www.openwall.com/lists/musl/2024/08/01/9
+ check_funcs += [ 'close_range' ]
+endif
foreach funcspec : check_funcs
define_name = 'HAVE_' + funcspec.underscorify().to_upper()
define_value = cxx.has_function(funcspec).to_int()
diff --git a/src/libutil/file-descriptor.cc b/src/libutil/file-descriptor.cc
index 4807869f9..f95d7b321 100644
--- a/src/libutil/file-descriptor.cc
+++ b/src/libutil/file-descriptor.cc
@@ -223,15 +223,27 @@ void closeExtraFDs()
constexpr int MAX_KEPT_FD = 2;
static_assert(std::max({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}) == MAX_KEPT_FD);
-#if __linux__
+ // Both Linux and FreeBSD support close_range.
+#if __linux__ || __FreeBSD__
+ auto closeRange = [](unsigned int first, unsigned int last, int flags) -> int {
+ // musl does not have close_range as of 2024-08-10
+ // patch: https://www.openwall.com/lists/musl/2024/08/01/9
+#ifdef HAVE_CLOSE_RANGE
+ return close_range(first, last, flags);
+#else
+ return syscall(SYS_close_range, first, last, flags);
+#endif
+ };
// first try to close_range everything we don't care about. if this
// returns an error with these parameters we're running on a kernel
// that does not implement close_range (i.e. pre 5.9) and fall back
// to the old method. we should remove that though, in some future.
- if (close_range(3, ~0U, 0) == 0) {
+ if (closeRange(3, ~0U, 0) == 0) {
return;
}
+#endif
+#if __linux__
try {
for (auto & s : readDirectory("/proc/self/fd")) {
auto fd = std::stoi(s.name);