msghdr is allocated on the stack at recv_prep, which means it may go out of scope before the kernel has a chance to complete the operation. This results in spurious test failures when we reach far enough into recv_fn to reuse the stack space before op_recvmsg executes. I found it easily reproducible when compiling with '-O0 -g3' to avoid gcc from optimizing further local variables out of the stack. Signed-off-by: Gabriel Krisman Bertazi --- test/send_recvmsg.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/send_recvmsg.c b/test/send_recvmsg.c index f2e1efc0..9154b6c0 100644 --- a/test/send_recvmsg.c +++ b/test/send_recvmsg.c @@ -32,10 +32,9 @@ static int ud; static int no_pbuf_ring; static int recv_prep(struct io_uring *ring, int *sockfd, struct iovec iov[], - int iov_count, int bgid, int async) + int iov_count, int bgid, int async, struct msghdr *msg) { struct sockaddr_in saddr; - struct msghdr msg; struct io_uring_sqe *sqe; int ret, val = 1; @@ -66,7 +65,7 @@ static int recv_prep(struct io_uring *ring, int *sockfd, struct iovec iov[], return 1; } - io_uring_prep_recvmsg(sqe, *sockfd, &msg, 0); + io_uring_prep_recvmsg(sqe, *sockfd, msg, 0); if (bgid) { iov->iov_base = NULL; sqe->flags |= IOSQE_BUFFER_SELECT; @@ -76,10 +75,10 @@ static int recv_prep(struct io_uring *ring, int *sockfd, struct iovec iov[], sqe->user_data = ++ud; if (async) sqe->flags |= IOSQE_ASYNC; - memset(&msg, 0, sizeof(msg)); - msg.msg_namelen = sizeof(struct sockaddr_in); - msg.msg_iov = iov; - msg.msg_iovlen = iov_count; + memset(msg, 0, sizeof(*msg)); + msg->msg_namelen = sizeof(struct sockaddr_in); + msg->msg_iov = iov; + msg->msg_iovlen = iov_count; ret = io_uring_submit(ring); if (ret <= 0) { @@ -168,6 +167,7 @@ static void *recv_fn(void *data) struct io_uring_buf_ring *br = NULL; char buf[MAX_MSG + 1]; struct iovec iov[MAX_IOV_COUNT]; + struct msghdr msg; struct io_uring ring; int ret, sockfd; @@ -225,7 +225,7 @@ static void *recv_fn(void *data) ret = recv_prep(&ring, &sockfd, iov, rd->iov_count, (rd->buf_ring || rd->buf_select) ? BUF_BGID : 0, - rd->async); + rd->async, &msg); if (ret) { fprintf(stderr, "recv_prep failed: %d\n", ret); goto err; -- 2.54.0