[PATCH 2/2] util: command: improve generic mass close of fds
Daniel P. Berrangé
berrange at redhat.com
Wed Aug 19 10:55:06 UTC 2020
On Wed, Aug 19, 2020 at 12:03:41PM +0200, Natanael Copa wrote:
> 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.
The patch isn't avoiding malloc - the virReportSystemError calls
all trigger mallocs in the error reporting code, as well as
triggering the logging code which mallocs.
The idea of using poll() as a fallback still makes sense as a
general feature though.
>
> This solves a deadlock with musl libc.
>
> Signed-off-by: Natanael Copa <ncopa at alpinelinux.org>
> ---
> src/util/vircommand.c | 76 +++++++++++++++++++++++++++++++++----------
> 1 file changed, 58 insertions(+), 18 deletions(-)
>
> diff --git a/src/util/vircommand.c b/src/util/vircommand.c
> index 17e5bb00d3..06579cfb44 100644
> --- a/src/util/vircommand.c
> +++ b/src/util/vircommand.c
> @@ -443,7 +443,7 @@ virExecCommon(virCommandPtr cmd, gid_t *groups, int ngroups)
> 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
> @@ -482,17 +482,7 @@ virCommandMassCloseGetFDsLinux(virCommandPtr cmd G_GNUC_UNUSED,
> VIR_DIR_CLOSE(dp);
> return ret;
> }
> -
> -# else /* !__linux__ */
> -
> -static int
> -virCommandMassCloseGetFDsGeneric(virCommandPtr cmd G_GNUC_UNUSED,
> - virBitmapPtr fds)
> -{
> - virBitmapSetAll(fds);
> - return 0;
> -}
> -# endif /* !__linux__ */
> +# endif /* __linux__ && __GLIBC__ */
>
> # ifdef __FreeBSD__
>
> @@ -546,7 +536,7 @@ virCommandMassClose(virCommandPtr cmd,
> return 0;
> }
>
> -# else /* ! __FreeBSD__ */
> +# elif defined(__GLIBC_) /* ! __FreeBSD__ */
>
> static int
> virCommandMassClose(virCommandPtr cmd,
> @@ -574,13 +564,8 @@ virCommandMassClose(virCommandPtr cmd,
> if (!(fds = virBitmapNew(openmax)))
> return -1;
>
> -# 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)) {
> @@ -598,6 +583,61 @@ virCommandMassClose(virCommandPtr cmd,
> 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__ */
>
> /*
> --
> 2.28.0
>
>
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
More information about the libvir-list
mailing list