public inbox for ltp@lists.linux.it
 help / color / mirror / Atom feed
* [LTP] [PATCH] aio_cancel_3-1: Rewrite test
@ 2026-02-24 16:27 Martin Doucha
  2026-02-25 15:49 ` Andrea Cervesato via ltp
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Martin Doucha @ 2026-02-24 16:27 UTC (permalink / raw)
  To: ltp

The test schedules multiple async writes into a file and then hopes that
at least one will block long enough that it can be canceled
before completion. Use a socket pair instead of a file to force async
writes to block indefinitely and make sure at least one can be canceled.
Then cancel all requests on the input socket and check that all signals
have been delivered and the expected number of requests has been canceled.
This fixes a race condition where aio_cancel() could be delayed until
after all writes have already completed, making the test unreliable.

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
 .../conformance/interfaces/aio_cancel/3-1.c   | 125 +++++++-----------
 1 file changed, 48 insertions(+), 77 deletions(-)

diff --git a/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/3-1.c b/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/3-1.c
index b74d11c6c..4a002d6ce 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/3-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/3-1.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, Bull SA. All rights reserved.
+ * Copyright (c) 2026 SUSE LLC
  * Created by:  Laurent.Vivier@bull.net
  * This file is licensed under the GPL license.  For the full content
  * of this license, see the COPYING file at the top level of this
@@ -14,44 +15,39 @@
  *
  * method:
  *
- *	we queue a lot of aio_write() with a valid sigevent to a file descriptor
- *	next we try to cancel all operations on this file descriptor
- *	we guess some have been finished, other are in progress,
- *	other are waiting
- *	we guess we can cancel all operations waiting
- *	then we analyze aio_error() in the event handler
- *	if aio_error() is ECANCELED, the test is passed
- *	otherwise, we don't know (perhaps we haven't cancel any operation ?)
- *	if number of sig event is not equal to number of aio_write()
- *	the test fails (in fact it hangs).
+ *	open a pair of sockets and queue writes to them with aio_write()
+ *	execute aio_cancel() on the socket
+ *	then analyze aio_error() in the event handler
+ *	if number of sig events is not equal to number of write requests,
+ *	the test fails
+ *	if aio_error() returns ECANCELED for the expected requests,
+ *	the test passes
  *
  */
 
-#include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <string.h>
-#include <errno.h>
 #include <signal.h>
-#include <stdlib.h>
-#include <aio.h>
 #include <time.h>
 
 #include "posixtest.h"
-#include "tempfile.h"
+#include "aio_test.h"
 
 #define TNAME "aio_cancel/3-1.c"
 
-#define BUF_NB		128
-#define BUF_SIZE	(1024 * 1024)
+#define WRITE_COUNT	8
+#define MAX_COMPLETE	3
+#define MAX_WAIT_RETRIES 100
 
-static volatile int countdown = BUF_NB;
+static volatile int countdown = WRITE_COUNT;
 static volatile int canceled;
+static int fds[2];
+static struct aiocb aiocb[WRITE_COUNT];
 
 static void sig_handler(int signum PTS_ATTRIBUTE_UNUSED, siginfo_t *info,
-    void *context PTS_ATTRIBUTE_UNUSED)
+	void *context PTS_ATTRIBUTE_UNUSED)
 {
 	struct aiocb *a = info->si_value.sival_ptr;
 
@@ -59,98 +55,73 @@ static void sig_handler(int signum PTS_ATTRIBUTE_UNUSED, siginfo_t *info,
 		canceled++;
 
 	aio_return(a);		/* free entry */
-
 	countdown--;
 }
 
 int main(void)
 {
-	char tmpfname[PATH_MAX];
-	int fd;
-	struct aiocb *aiocb_list[BUF_NB];
-	struct aiocb *aiocb;
 	struct sigaction action;
 	struct timespec processing_completion_ts = {0, 10000000};
 	int i;
 
 	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L) {
-		printf(TNAME " %ld\n", sysconf(_SC_ASYNCHRONOUS_IO));
+		printf(TNAME " Unsupported AIO version: %ld\n",
+			sysconf(_SC_ASYNCHRONOUS_IO));
 		return PTS_UNSUPPORTED;
 	}
 
-	PTS_GET_TMP_FILENAME(tmpfname, "pts_aio_cancel_3_1");
-	unlink(tmpfname);
-	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
-	if (fd == -1) {
-		printf(TNAME " Error at open(): %s\n", strerror(errno));
-		return PTS_UNRESOLVED;
-	}
-
-	unlink(tmpfname);
-
 	/* install signal handler */
-
 	action.sa_sigaction = sig_handler;
 	sigemptyset(&action.sa_mask);
 	action.sa_flags = SA_SIGINFO | SA_RESTART;
+
 	if (sigaction(SIGRTMIN + 1, &action, NULL)) {
 		printf(TNAME " Error at sigaction(): %s\n", strerror(errno));
-		return PTS_FAIL;
+		return PTS_UNRESOLVED;
 	}
 
-	/* create AIO req */
-
-	for (i = 0; i < BUF_NB; i++) {
-		aiocb = malloc(sizeof(struct aiocb));
-		if (aiocb == NULL) {
-			printf(TNAME " Error at malloc(): %s\n",
-			       strerror(errno));
-			return PTS_FAIL;
-		}
-
-		aiocb->aio_fildes = fd;
-		aiocb->aio_buf = malloc(BUF_SIZE);
-		if (aiocb->aio_buf == NULL) {
-			printf(TNAME " Error at malloc(): %s\n",
-			       strerror(errno));
-			return PTS_FAIL;
-		}
-
-		aiocb->aio_nbytes = BUF_SIZE;
-		aiocb->aio_offset = 0;
-
-		aiocb->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
-		aiocb->aio_sigevent.sigev_signo = SIGRTMIN + 1;
-		aiocb->aio_sigevent.sigev_value.sival_ptr = aiocb;
-		aiocb->aio_reqprio = 0;
+	if (setup_aio(TNAME, fds, aiocb, WRITE_COUNT))
+		return PTS_UNRESOLVED;
 
-		aiocb_list[i] = aiocb;
-	}
+	/* submit AIO req */
+	for (i = 0; i < WRITE_COUNT; i++) {
+		aiocb[i].aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+		aiocb[i].aio_sigevent.sigev_signo = SIGRTMIN + 1;
+		aiocb[i].aio_sigevent.sigev_value.sival_ptr = &aiocb[i];
+		aiocb[i].aio_reqprio = 0;
 
-	for (i = 0; i < BUF_NB; i++) {
-		if (aio_write(aiocb_list[i]) == -1) {
+		if (aio_write(&aiocb[i]) == -1) {
 			printf(TNAME " loop %d: Error at aio_write(): %s\n",
-			       i, strerror(errno));
+				i, strerror(errno));
+			cleanup_aio(fds, aiocb, WRITE_COUNT);
 			return PTS_FAIL;
 		}
 	}
 
-	/* try to cancel all
-	 * we hope to have enough time to cancel at least one
-	 */
-
-	if (aio_cancel(fd, NULL) == -1) {
+	/* cancel all requests */
+	if (aio_cancel(fds[0], NULL) == -1) {
 		printf(TNAME " Error at aio_cancel(): %s\n", strerror(errno));
+		cleanup_aio(fds, aiocb, WRITE_COUNT);
 		return PTS_FAIL;
 	}
 
-	close(fd);
+	cleanup_aio(fds, aiocb, WRITE_COUNT);
 
-	while (countdown)
+	/* wait for signal delivery */
+	for (i = 0; countdown && i < MAX_WAIT_RETRIES; i++)
 		nanosleep(&processing_completion_ts, NULL);
 
-	if (!canceled)
-		return PTS_UNRESOLVED;
+	if (countdown) {
+		printf(TNAME " %d task completion signals were not delivered",
+			countdown);
+		return PTS_FAIL;
+	}
+
+	if (canceled < WRITE_COUNT - MAX_COMPLETE) {
+		printf(TNAME " %d AIO requests got canceled, expected %d",
+			canceled, WRITE_COUNT - MAX_COMPLETE);
+		return PTS_FAIL;
+	}
 
 	printf("Test PASSED\n");
 	return PTS_PASS;
-- 
2.52.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [LTP] [PATCH] aio_cancel_3-1: Rewrite test
  2026-02-24 16:27 [LTP] [PATCH] aio_cancel_3-1: Rewrite test Martin Doucha
@ 2026-02-25 15:49 ` Andrea Cervesato via ltp
  2026-03-09 14:27 ` Petr Vorel
  2026-03-16 10:33 ` Andrea Cervesato via ltp
  2 siblings, 0 replies; 4+ messages in thread
From: Andrea Cervesato via ltp @ 2026-02-25 15:49 UTC (permalink / raw)
  To: Martin Doucha, ltp

Hi!

Acked-by: Andrea Cervesato <andrea.cervesato@suse.com>


-- 
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [LTP] [PATCH] aio_cancel_3-1: Rewrite test
  2026-02-24 16:27 [LTP] [PATCH] aio_cancel_3-1: Rewrite test Martin Doucha
  2026-02-25 15:49 ` Andrea Cervesato via ltp
@ 2026-03-09 14:27 ` Petr Vorel
  2026-03-16 10:33 ` Andrea Cervesato via ltp
  2 siblings, 0 replies; 4+ messages in thread
From: Petr Vorel @ 2026-03-09 14:27 UTC (permalink / raw)
  To: Martin Doucha; +Cc: ltp

Hi Martin,

> The test schedules multiple async writes into a file and then hopes that
> at least one will block long enough that it can be canceled
> before completion. Use a socket pair instead of a file to force async
> writes to block indefinitely and make sure at least one can be canceled.
> Then cancel all requests on the input socket and check that all signals
> have been delivered and the expected number of requests has been canceled.
> This fixes a race condition where aio_cancel() could be delayed until
> after all writes have already completed, making the test unreliable.

Thanks for the fix, merged!
Also thank you for additional error log output and formatting cleanup.

I suppose some of the tests still need to be fixed ([46]-1.c queue a lot of
aio_write()).

Kind regards,
Petr

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [LTP] [PATCH] aio_cancel_3-1: Rewrite test
  2026-02-24 16:27 [LTP] [PATCH] aio_cancel_3-1: Rewrite test Martin Doucha
  2026-02-25 15:49 ` Andrea Cervesato via ltp
  2026-03-09 14:27 ` Petr Vorel
@ 2026-03-16 10:33 ` Andrea Cervesato via ltp
  2 siblings, 0 replies; 4+ messages in thread
From: Andrea Cervesato via ltp @ 2026-03-16 10:33 UTC (permalink / raw)
  To: Martin Doucha; +Cc: ltp

LGTM
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-03-16 10:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-24 16:27 [LTP] [PATCH] aio_cancel_3-1: Rewrite test Martin Doucha
2026-02-25 15:49 ` Andrea Cervesato via ltp
2026-03-09 14:27 ` Petr Vorel
2026-03-16 10:33 ` Andrea Cervesato via ltp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox