|
@@ -808,11 +808,12 @@ int qemu_msync(void *addr, size_t length, int fd)
|
|
|
return msync(addr, length, MS_SYNC);
|
|
|
}
|
|
|
|
|
|
-static bool qemu_close_all_open_fd_proc(void)
|
|
|
+static bool qemu_close_all_open_fd_proc(const int *skip, unsigned int nskip)
|
|
|
{
|
|
|
struct dirent *de;
|
|
|
int fd, dfd;
|
|
|
DIR *dir;
|
|
|
+ unsigned int skip_start = 0, skip_end = nskip;
|
|
|
|
|
|
dir = opendir("/proc/self/fd");
|
|
|
if (!dir) {
|
|
@@ -823,8 +824,33 @@ static bool qemu_close_all_open_fd_proc(void)
|
|
|
dfd = dirfd(dir);
|
|
|
|
|
|
for (de = readdir(dir); de; de = readdir(dir)) {
|
|
|
+ bool close_fd = true;
|
|
|
+
|
|
|
+ if (de->d_name[0] == '.') {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
fd = atoi(de->d_name);
|
|
|
- if (fd != dfd) {
|
|
|
+ if (fd == dfd) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (unsigned int i = skip_start; i < skip_end; i++) {
|
|
|
+ if (fd < skip[i]) {
|
|
|
+ /* We are below the next skipped fd, break */
|
|
|
+ break;
|
|
|
+ } else if (fd == skip[i]) {
|
|
|
+ close_fd = false;
|
|
|
+ /* Restrict the range as we found fds matching start/end */
|
|
|
+ if (i == skip_start) {
|
|
|
+ skip_start++;
|
|
|
+ } else if (i == skip_end) {
|
|
|
+ skip_end--;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (close_fd) {
|
|
|
close(fd);
|
|
|
}
|
|
|
}
|
|
@@ -833,24 +859,60 @@ static bool qemu_close_all_open_fd_proc(void)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-static bool qemu_close_all_open_fd_close_range(void)
|
|
|
+static bool qemu_close_all_open_fd_close_range(const int *skip,
|
|
|
+ unsigned int nskip,
|
|
|
+ int open_max)
|
|
|
{
|
|
|
#ifdef CONFIG_CLOSE_RANGE
|
|
|
- int r = close_range(0, ~0U, 0);
|
|
|
- if (!r) {
|
|
|
- /* Success, no need to try other ways. */
|
|
|
- return true;
|
|
|
- }
|
|
|
-#endif
|
|
|
+ int max_fd = open_max - 1;
|
|
|
+ int first = 0, last;
|
|
|
+ unsigned int cur_skip = 0;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ do {
|
|
|
+ /* Find the start boundary of the range to close */
|
|
|
+ while (cur_skip < nskip && first == skip[cur_skip]) {
|
|
|
+ cur_skip++;
|
|
|
+ first++;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Find the upper boundary of the range to close */
|
|
|
+ last = max_fd;
|
|
|
+ if (cur_skip < nskip) {
|
|
|
+ last = skip[cur_skip] - 1;
|
|
|
+ last = MIN(last, max_fd);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* With the adjustments to the range, we might be done. */
|
|
|
+ if (first > last) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = close_range(first, last, 0);
|
|
|
+ if (ret < 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ first = last + 1;
|
|
|
+ } while (last < max_fd);
|
|
|
+
|
|
|
+ return true;
|
|
|
+#else
|
|
|
return false;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
-static void qemu_close_all_open_fd_fallback(void)
|
|
|
+static void qemu_close_all_open_fd_fallback(const int *skip, unsigned int nskip,
|
|
|
+ int open_max)
|
|
|
{
|
|
|
- int open_max = sysconf(_SC_OPEN_MAX), i;
|
|
|
+ unsigned int cur_skip = 0;
|
|
|
|
|
|
/* Fallback */
|
|
|
- for (i = 0; i < open_max; i++) {
|
|
|
+ for (int i = 0; i < open_max; i++) {
|
|
|
+ if (cur_skip < nskip && i == skip[cur_skip]) {
|
|
|
+ cur_skip++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
close(i);
|
|
|
}
|
|
|
}
|
|
@@ -858,10 +920,14 @@ static void qemu_close_all_open_fd_fallback(void)
|
|
|
/*
|
|
|
* Close all open file descriptors.
|
|
|
*/
|
|
|
-void qemu_close_all_open_fd(void)
|
|
|
+void qemu_close_all_open_fd(const int *skip, unsigned int nskip)
|
|
|
{
|
|
|
- if (!qemu_close_all_open_fd_close_range() &&
|
|
|
- !qemu_close_all_open_fd_proc()) {
|
|
|
- qemu_close_all_open_fd_fallback();
|
|
|
+ int open_max = sysconf(_SC_OPEN_MAX);
|
|
|
+
|
|
|
+ assert(skip != NULL || nskip == 0);
|
|
|
+
|
|
|
+ if (!qemu_close_all_open_fd_close_range(skip, nskip, open_max) &&
|
|
|
+ !qemu_close_all_open_fd_proc(skip, nskip)) {
|
|
|
+ qemu_close_all_open_fd_fallback(skip, nskip, open_max);
|
|
|
}
|
|
|
}
|