From fc11865a1bba5c0ce27991e80f018dd8862b48e7 Mon Sep 17 00:00:00 2001 From: anton Date: Sat, 8 May 2021 06:53:19 +0000 Subject: [PATCH] Fix a race in the kqueue-read test. If the writer thread managed to fill up the pipe buffer, it will hang in write(2) waiting for the pipe to become writeable again. While doing so, it cannot observe that the kqueue thread as already finished implying that ctx_thread_alive() would return false, meaning no further writes are wanted. Therefore open the pipe in non blocking mode and just ignore EAGAIN errors while writing. --- regress/sys/kern/pipe/test-kqueue.c | 31 +++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/regress/sys/kern/pipe/test-kqueue.c b/regress/sys/kern/pipe/test-kqueue.c index e7da8c6eccf..36ad8d936de 100644 --- a/regress/sys/kern/pipe/test-kqueue.c +++ b/regress/sys/kern/pipe/test-kqueue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test-kqueue.c,v 1.2 2019/12/24 11:42:34 anton Exp $ */ +/* $OpenBSD: test-kqueue.c,v 1.3 2021/05/08 06:53:19 anton Exp $ */ /* * Copyright (c) 2019 Anton Lindqvist @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include #include @@ -48,7 +50,7 @@ struct context { pthread_mutex_t c_mtx; }; -static void ctx_setup(struct context *, enum kqueue_mode); +static void ctx_setup(struct context *, enum kqueue_mode, int); static void ctx_teardown(struct context *); static int ctx_thread_alive(struct context *); static void ctx_thread_start(struct context *); @@ -65,16 +67,18 @@ test_kqueue_read(void) { struct context ctx; - ctx_setup(&ctx, KQUEUE_READ); + ctx_setup(&ctx, KQUEUE_READ, O_NONBLOCK); ctx_thread_start(&ctx); while (ctx_thread_alive(&ctx)) { ssize_t n; - unsigned char c = 'r'; - n = write(ctx.c_pipe[1], &c, 1); - if (n == -1) + n = write(ctx.c_pipe[1], &ctx.c_buf[0], 1); + if (n == -1) { + if (errno == EAGAIN) + continue; err(1, "write"); + } if (n != 1) errx(1, "write: %ld != 1", n); } @@ -92,7 +96,7 @@ test_kqueue_read_eof(void) { struct context ctx; - ctx_setup(&ctx, KQUEUE_READ_EOF); + ctx_setup(&ctx, KQUEUE_READ_EOF, 0); ctx_thread_start(&ctx); while (ctx_thread_alive(&ctx)) { @@ -117,7 +121,7 @@ test_kqueue_write(void) struct context ctx; ssize_t n; - ctx_setup(&ctx, KQUEUE_WRITE); + ctx_setup(&ctx, KQUEUE_WRITE, 0); n = write(ctx.c_pipe[1], ctx.c_buf, ctx.c_bufsiz); if (n == -1) @@ -153,15 +157,20 @@ test_kqueue_write_eof(void) } static void -ctx_setup(struct context *ctx, enum kqueue_mode mode) +ctx_setup(struct context *ctx, enum kqueue_mode mode, int flags) { int error; ctx->c_mode = mode; ctx->c_alive = 1; - if (pipe(ctx->c_pipe) == -1) - err(1, "pipe"); + if (flags) { + if (pipe2(ctx->c_pipe, flags) == -1) + err(1, "pipe"); + } else { + if (pipe(ctx->c_pipe) == -1) + err(1, "pipe"); + } ctx->c_kq = kqueue(); if (ctx->c_kq == -1) -- 2.20.1