epoll_handler is a stack variable and must not be accessed after it goes
out of scope:
if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
AioHandler epoll_handler;
...
add_pollfd(&epoll_handler);
ret = aio_epoll(ctx, pollfds, npfd, timeout);
} ...
...
/* if we have any readable fds, dispatch event */
if (ret > 0) {
for (i = 0; i < npfd; i++) {
nodes[i]->pfd.revents = pollfds[i].revents;
}
}
nodes[0] is &epoll_handler, which has already gone out of scope.
There is no need to use pollfds[] for epoll. We don't need an
AioHandler for the epoll fd.
Signed-off-by: Stefan Hajnoczi
---
util/aio-posix.c | 20
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/util/aio-posix.c b/util/aio-posix.c
index a4977f538e..31a8e03ca7 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -104,17 +104,18 @@ static void aio_epoll_update(AioContext *ctx, AioHandler
*node, bool is_new)
}
}
-static int aio_epoll(AioContext *ctx, GPollFD *pfds,
- unsigned npfd, int64_t timeout)
+static int aio_epoll(AioContext *ctx, int64_t timeout)
{
+GPollFD pfd = {
+.fd = ctx->epollfd,
+.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR,
+};
AioHandler *node;
int i, ret = 0;
struct epoll_event events[128];
-assert(npfd == 1);
-assert(pfds[0].fd == ctx->epollfd);
if (timeout > 0) {
-ret = qemu_poll_ns(pfds, npfd, timeout);
+ret = qemu_poll_ns(&pfd, 1, timeout);
}
if (timeout <= 0 || ret > 0) {
ret = epoll_wait(ctx->epollfd, events,
@@ -658,13 +659,8 @@ bool aio_poll(AioContext *ctx, bool blocking)
/* wait until next event */
if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
-AioHandler epoll_handler;
-
-epoll_handler.pfd.fd = ctx->epollfd;
-epoll_handler.pfd.events = G_IO_IN | G_IO_OUT | G_IO_HUP |
G_IO_ERR;
-npfd = 0;
-add_pollfd(&epoll_handler);
-ret = aio_epoll(ctx, pollfds, npfd, timeout);
+npfd = 0; /* pollfds[] is not being used */
+ret = aio_epoll(ctx, timeout);
} else {
ret = qemu_poll_ns(pollfds, npfd, timeout);
}
--
2.24.1