From 1f60133bfbd872010f4b1d524d05e70623ff0360 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 2 Jul 2023 10:49:49 +0200 Subject: [PATCH] BUILD: debug: avoid a build warning related to epoll_wait() in debug code Ilya reported in issue #2193 that the latest Fedora complains about us passing NULL to epoll_wait() in the "debug dev fd" code to try to detect an epoll FD. That was intentional to get the kernel's verifications and make sure we're facing a poller, but since such a warning comes from the libc, it's possible that it plans to replace the syscall with a wrapper in the near future (e.g. epoll_pwait()), and that just hiding the NULL (as was confirmed to work) might just postpone the problem. Let's take another approach, instead we'll create a new dummy FD that we'll try to remove from the epoll set using epoll_ctl(). Since we created the FD we're certain it cannot be there. In this case (and only in this case) epoll_ctl() will return -ENOENT, otherwise it will typically return EINVAL or EBADF. It was verified that it works and doesn't return false positives for other FD types. It should be backported to the branches that contain a backport of the commit which introduced the feature, apparently as far as 2.4: 5be7c198e ("DEBUG: cli: add a new "debug dev fd" expert command") --- src/debug.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/debug.c b/src/debug.c index 474a6647f..89c7a53de 100644 --- a/src/debug.c +++ b/src/debug.c @@ -1384,7 +1384,27 @@ static int debug_iohandler_fd(struct appctx *appctx) S_ISLNK(statbuf.st_mode) ? "link": S_ISSOCK(statbuf.st_mode) ? "sock": #ifdef USE_EPOLL - epoll_wait(fd, NULL, 0, 0) != -1 || errno != EBADF ? "epol": + /* trick: epoll_ctl() will return -ENOENT when trying + * to remove from a valid epoll FD an FD that was not + * registered against it. But we don't want to risk + * disabling a random FD. Instead we'll create a new + * one by duplicating 0 (it should be valid since + * pointing to a terminal or /dev/null), and try to + * remove it. + */ + ({ + int fd2 = dup(0); + int ret = fd2; + if (ret >= 0) { + ret = epoll_ctl(fd, EPOLL_CTL_DEL, fd2, NULL); + if (ret == -1 && errno == ENOENT) + ret = 0; // that's a real epoll + else + ret = -1; // it's something else + close(fd2); + } + ret; + }) == 0 ? "epol" : #endif "????", (uint)statbuf.st_mode & 07777,