e17f291d75
Alpine Linux includes two patches to fix deadlocks with musl. Because upstream is not interested in merging these patches, conditionally apply one only for musl archs. The other is guarded by conditional compilation directives, so there is no harm in applying the patch unconditionally. Closes #25905.
131 lines
3.4 KiB
Diff
131 lines
3.4 KiB
Diff
https://www.redhat.com/archives/libvir-list/2020-August/msg00598.html
|
|
|
|
Add a portable generic implementation of virMassClose as fallback on
|
|
non-FreeBSD and non-glibc.
|
|
|
|
This implementation uses poll(2) to look for open files to keep
|
|
performance reasonable while not using any mallocs.
|
|
|
|
This solves a deadlock with musl libc.
|
|
|
|
Signed-off-by: Natanael Copa <ncopa alpinelinux org>
|
|
---
|
|
src/util/vircommand.c | 76 +++++++++++++++++++++++++++++++++----------
|
|
1 file changed, 58 insertions(+), 18 deletions(-)
|
|
|
|
diff -ur src/util/vircommand.c src/util/vircommand.c
|
|
--- src/util/vircommand.c
|
|
+++ src/util/vircommand.c
|
|
@@ -443,7 +443,7 @@
|
|
return 0;
|
|
}
|
|
|
|
-# ifdef __linux__
|
|
+# if defined(__linux__) && defined(__GLIBC__)
|
|
/* On Linux, we can utilize procfs and read the table of opened
|
|
* FDs and selectively close only those FDs we don't want to pass
|
|
* onto child process (well, the one we will exec soon since this
|
|
@@ -478,17 +478,7 @@
|
|
|
|
return 0;
|
|
}
|
|
-
|
|
-# else /* !__linux__ */
|
|
-
|
|
-static int
|
|
-virCommandMassCloseGetFDsGeneric(virCommandPtr cmd G_GNUC_UNUSED,
|
|
- virBitmapPtr fds)
|
|
-{
|
|
- virBitmapSetAll(fds);
|
|
- return 0;
|
|
-}
|
|
-# endif /* !__linux__ */
|
|
+# endif /* __linux__ && __GLIBC__ */
|
|
|
|
# ifdef __FreeBSD__
|
|
|
|
@@ -542,7 +532,7 @@
|
|
return 0;
|
|
}
|
|
|
|
-# else /* ! __FreeBSD__ */
|
|
+# elif defined(__GLIBC__) /* ! __FreeBSD__ */
|
|
|
|
static int
|
|
virCommandMassClose(virCommandPtr cmd,
|
|
@@ -569,13 +559,8 @@
|
|
|
|
fds = virBitmapNew(openmax);
|
|
|
|
-# ifdef __linux__
|
|
if (virCommandMassCloseGetFDsLinux(cmd, fds) < 0)
|
|
return -1;
|
|
-# else
|
|
- if (virCommandMassCloseGetFDsGeneric(cmd, fds) < 0)
|
|
- return -1;
|
|
-# endif
|
|
|
|
fd = virBitmapNextSetBit(fds, 2);
|
|
for (; fd >= 0; fd = virBitmapNextSetBit(fds, fd)) {
|
|
@@ -593,6 +578,61 @@
|
|
return 0;
|
|
}
|
|
|
|
+#else /* ! __FreeBSD__ && ! __GLIBC__ */
|
|
+static int
|
|
+virCommandMassClose(virCommandPtr cmd,
|
|
+ int childin,
|
|
+ int childout,
|
|
+ int childerr)
|
|
+{
|
|
+ static struct pollfd pfds[1024];
|
|
+ int fd = 0;
|
|
+ int i, total;
|
|
+ int max_fd = sysconf(_SC_OPEN_MAX);
|
|
+
|
|
+ if (max_fd < 0) {
|
|
+ virReportSystemError(errno, "%s", _("sysconf(_SC_OPEN_MAX) failed"));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ total = max_fd - fd;
|
|
+ for (i = 0; i < (total < 1024 ? total : 1024); i++)
|
|
+ pfds[i].events = 0;
|
|
+
|
|
+ while (fd < max_fd) {
|
|
+ int nfds, r = 0;
|
|
+
|
|
+ total = max_fd - fd;
|
|
+ nfds = total < 1024 ? total : 1024;
|
|
+
|
|
+ for (i = 0; i < nfds; i++)
|
|
+ pfds[i].fd = fd + i;
|
|
+
|
|
+ do {
|
|
+ r = poll(pfds, nfds, 0);
|
|
+ } while (r == -1 && errno == EINTR);
|
|
+
|
|
+ if (r < 0) {
|
|
+ virReportSystemError(errno, "%s", _("poll() failed"));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < nfds; i++)
|
|
+ if (pfds[i].revents != POLLNVAL) {
|
|
+ if (pfds[i].fd == childin || pfds[i].fd == childout || pfds[i].fd == childerr)
|
|
+ continue;
|
|
+ if (!virCommandFDIsSet(cmd, pfds[i].fd)) {
|
|
+ VIR_MASS_CLOSE(pfds[i].fd);
|
|
+ } else if (virSetInherit(pfds[i].fd, true) < 0) {
|
|
+ virReportSystemError(errno, _("failed to preserve fd %d"), pfds[i].fd);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+ fd += nfds;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
# endif /* ! __FreeBSD__ */
|
|
|
|
/*
|