summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c54
1 files changed, 38 insertions, 16 deletions
diff --git a/src/util.c b/src/util.c
index 3a855c1be4..73481abee6 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2207,13 +2207,47 @@ int fd_cloexec(int fd, bool cloexec) {
return 0;
}
+static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
+ unsigned i;
+
+ assert(n_fdset == 0 || fdset);
+
+ for (i = 0; i < n_fdset; i++)
+ if (fdset[i] == fd)
+ return true;
+
+ return false;
+}
+
int close_all_fds(const int except[], unsigned n_except) {
DIR *d;
struct dirent *de;
int r = 0;
- if (!(d = opendir("/proc/self/fd")))
- return -errno;
+ assert(n_except == 0 || except);
+
+ d = opendir("/proc/self/fd");
+ if (!d) {
+ int fd;
+ struct rlimit rl;
+
+ /* When /proc isn't available (for example in chroots)
+ * the fallback is brute forcing through the fd
+ * table */
+
+ assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
+ for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
+
+ if (fd_in_set(fd, except, n_except))
+ continue;
+
+ if (close_nointr(fd) < 0)
+ if (errno != EBADF && r == 0)
+ r = -errno;
+ }
+
+ return r;
+ }
while ((de = readdir(d))) {
int fd = -1;
@@ -2231,20 +2265,8 @@ int close_all_fds(const int except[], unsigned n_except) {
if (fd == dirfd(d))
continue;
- if (except) {
- bool found;
- unsigned i;
-
- found = false;
- for (i = 0; i < n_except; i++)
- if (except[i] == fd) {
- found = true;
- break;
- }
-
- if (found)
- continue;
- }
+ if (fd_in_set(fd, except, n_except))
+ continue;
if (close_nointr(fd) < 0) {
/* Valgrind has its own FD and doesn't want to have it closed */