diff --git a/configure.ac b/configure.ac index 2483dfeac2..4ff0d3eb65 100644 --- a/configure.ac +++ b/configure.ac @@ -483,6 +483,8 @@ else ac_cv_func_port_create=no fi +AC_CHECK_FUNCS([eventfd]) + # --with-persistent-storage AC_ARG_WITH(persistent-storage, AS_HELP_STRING([--with-persistent-storage], diff --git a/include/Makefile.am b/include/Makefile.am index 347724d70a..a44b32ccbd 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -95,6 +95,7 @@ nobase_noinst_HEADERS = \ vcs_version.h \ vct.h \ vcurses.h \ + vefd.h \ venc.h \ vend.h \ vev.h \ diff --git a/include/vefd.h b/include/vefd.h new file mode 100644 index 0000000000..5f41bada1e --- /dev/null +++ b/include/vefd.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2025 Varnish Software AS + * All rights reserved. + * + * Author: Dridi Boukelmoune + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +struct vefd { + unsigned magic; +#define VEFD_MAGIC 0x1548c1a6 + int poll_fd; + int priv_fd; +}; + +#define VEFD_INIT(vefd) \ + do { \ + INIT_OBJ(vefd, VEFD_MAGIC); \ + (vefd)->poll_fd = -1; \ + (vefd)->priv_fd = -1; \ + } while (0) + +int VEFD_Open(struct vefd *); +int VEFD_Signal(struct vefd *); +int VEFD_Clear(struct vefd *); +int VEFD_Close(struct vefd *); diff --git a/lib/libvarnish/Makefile.am b/lib/libvarnish/Makefile.am index 2210911107..1e7e984b8b 100644 --- a/lib/libvarnish/Makefile.am +++ b/lib/libvarnish/Makefile.am @@ -23,6 +23,7 @@ libvarnish_la_SOURCES = \ vcli_serve.c \ vct.c \ venc.c \ + vefd.c \ version.c \ vev.c \ vfil.c \ diff --git a/lib/libvarnish/vefd.c b/lib/libvarnish/vefd.c new file mode 100644 index 0000000000..8be1c70311 --- /dev/null +++ b/lib/libvarnish/vefd.c @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 2025 Varnish Software AS + * All rights reserved. + * + * Author: Dridi Boukelmoune + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "config.h" + +#if HAVE_EVENTFD +# include +#else +# include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if HAVE_EVENTFD +int +VEFD_Open(struct vefd *vefd) +{ + + CHECK_OBJ_NOTNULL(vefd, VEFD_MAGIC); + assert(vefd->poll_fd == -1); + assert(vefd->priv_fd == -1); + + vefd->poll_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + return (vefd->poll_fd); +} + +int +VEFD_Signal(struct vefd *vefd) +{ + int64_t buf = 1; + + CHECK_OBJ_NOTNULL(vefd, VEFD_MAGIC); + assert(vefd->poll_fd >= 0); + assert(vefd->priv_fd == -1); + assert(write(vefd->poll_fd, &buf, sizeof buf) == sizeof buf); + return (0); +} + +int +VEFD_Clear(struct vefd *vefd) +{ + int64_t buf; + + CHECK_OBJ_NOTNULL(vefd, VEFD_MAGIC); + assert(vefd->poll_fd >= 0); + assert(vefd->priv_fd == -1); + assert(read(vefd->poll_fd, &buf, sizeof buf) == sizeof buf); + return (0); +} + +int +VEFD_Close(struct vefd *vefd) +{ + + CHECK_OBJ_NOTNULL(vefd, VEFD_MAGIC); + assert(vefd->poll_fd >= 0); + assert(vefd->priv_fd == -1); + closefd(&vefd->poll_fd); + return (0); +} +#else /* !HAVE_EVENTFD */ +int +VEFD_Open(struct vefd *vefd) +{ + int fd[2]; + + CHECK_OBJ_NOTNULL(vefd, VEFD_MAGIC); + assert(vefd->poll_fd == -1); + assert(vefd->priv_fd == -1); + + if (pipe(fd) < 0) + return (-1); + + AZ(fcntl(fd[0], F_SETFL, O_CLOEXEC|O_NONBLOCK)); + AZ(fcntl(fd[1], F_SETFL, O_CLOEXEC|O_NONBLOCK)); + vefd->poll_fd = fd[0]; + vefd->priv_fd = fd[1]; + return (0); +} + +int +VEFD_Signal(struct vefd *vefd) +{ + ssize_t r; + + CHECK_OBJ_NOTNULL(vefd, VEFD_MAGIC); + assert(vefd->poll_fd >= 0); + assert(vefd->priv_fd >= 0); + assert(vefd->poll_fd != vefd->priv_fd); + r = write(vefd->priv_fd, "", 1); + if (r < 0 && errno != EAGAIN && errno != EWOULDBLOCK) + return (-1); + return (0); +} + +int +VEFD_Clear(struct vefd *vefd) +{ + char buf[64]; + ssize_t r; + + CHECK_OBJ_NOTNULL(vefd, VEFD_MAGIC); + assert(vefd->poll_fd >= 0); + assert(vefd->priv_fd >= 0); + assert(vefd->poll_fd != vefd->priv_fd); + do { + r = read(vefd->poll_fd, buf, sizeof buf); + } while (r > 0); + if (errno != EAGAIN && errno != EWOULDBLOCK) + return (-1); + return (0); +} + +int +VEFD_Close(struct vefd *vefd) +{ + + CHECK_OBJ_NOTNULL(vefd, VEFD_MAGIC); + assert(vefd->poll_fd >= 0); + assert(vefd->priv_fd >= 0); + assert(vefd->poll_fd != vefd->priv_fd); + closefd(&vefd->poll_fd); + closefd(&vefd->priv_fd); + return (0); +} +#endif /* HAVE_EVENTFD */