When I added support for nolibc x86-64, I found this test failed. Long story short, we provide our own `free()` that always unmaps the VM with `munmap()`. It makes the CQE return -EFAULT because the kernel reads unmapped user memory from the pending `write()` SQE. I believe this test can run properly with libc build because `free()` from libc doesn't always unmap the memory, instead it uses free list on the userspace and the freed heap may still be userspace addressable. Fix this by deferring the free. Cc: Jens Axboe <axboe@xxxxxxxxx> Fixes: 2edfa3f84bcc44612b7a04caf1f048f5406fcc7a ("Add test case for thread exiting with pending IO") Signed-off-by: Ammar Faizi <ammar.faizi@xxxxxxxxxxxxxxxxxxxxx> --- test/thread-exit.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/thread-exit.c b/test/thread-exit.c index 7f66028..05509fb 100644 --- a/test/thread-exit.c +++ b/test/thread-exit.c @@ -26,8 +26,18 @@ struct d { unsigned long off; int pipe_fd; int err; + int i; }; +char *g_buf[NR_IOS] = {NULL}; + +static void free_g_buf(void) +{ + int i; + for (i = 0; i < NR_IOS; i++) + free(g_buf[i]); +} + static void *do_io(void *data) { struct d *d = data; @@ -36,6 +46,7 @@ static void *do_io(void *data) int ret; buffer = t_malloc(WSIZE); + g_buf[d->i] = buffer; memset(buffer, 0x5a, WSIZE); sqe = io_uring_get_sqe(d->ring); if (!sqe) { @@ -55,8 +66,6 @@ static void *do_io(void *data) ret = io_uring_submit(d->ring); if (ret != 2) d->err++; - - free(buffer); return NULL; } @@ -103,6 +112,7 @@ int main(int argc, char *argv[]) d.pipe_fd = fds[0]; d.err = 0; for (i = 0; i < NR_IOS; i++) { + d.i = i; memset(&thread, 0, sizeof(thread)); pthread_create(&thread, NULL, do_io, &d); pthread_join(thread, NULL); @@ -125,7 +135,9 @@ int main(int argc, char *argv[]) io_uring_cqe_seen(&ring, cqe); } + free_g_buf(); return d.err; err: + free_g_buf(); return 1; } -- 2.30.2