Linux Test Project
 help / color / mirror / Atom feed
From: Martin Doucha <mdoucha@suse.cz>
To: ltp@lists.linux.it
Subject: [LTP] [PATCH v2 2/2] aio_cancel_6-1: Rewrite test
Date: Wed, 29 Apr 2026 16:53:12 +0200	[thread overview]
Message-ID: <20260429145314.79256-2-mdoucha@suse.cz> (raw)
In-Reply-To: <20260429145314.79256-1-mdoucha@suse.cz>

The test schedules multiple async writes into a file and then hopes that
at least one will block long enough that aio_cancel() will cancel it.
Use a socket pair instead of a file to force async writes to block
indefinitely, then cancel one of the blocked writes.  This fixes a race
condition where aio_cancel() could be called after the target write
has already finished. Also improve result checks to verify that
non-canceled writes are still pending.

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---

Changes since v1: Removed strerror() call on aio_cancel() return value

 .../conformance/interfaces/aio_cancel/6-1.c   | 135 +++++++-----------
 1 file changed, 48 insertions(+), 87 deletions(-)

diff --git a/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/6-1.c b/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/6-1.c
index 2e3d64742..623dcd8e5 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/6-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/6-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,128 +15,88 @@
  *
  * method:
  *
- *	queue a lot of aio_write() to a given fildes.
- *	try to cancel the last one submited
- *	if aio_error() is ECANCELED and aio_cancel() is AIO_CANCELED
- *	test is passed
- *	if aio_error() is ECANCELED and aio_cancel() is NOT AIO_CANCELED
- *	test is failed
- *	if there is no aio_error() with ECANCELED and
- *	aio_cancel() is AIO_CANCELED
- *	test is failed
- *	otherwise test is unresolved
+ *	queue multiple aio_write()s to a given socket
+ *	try to cancel a task which hasn't been started yet
+ *	if aio_cancel() return value is not AIO_CANCELED, the test failed
+ *	for blocked tasks, aio_error() must be:
+ *	- ECANCELED if aio_cancel() was called on it
+ *	- EINPROGRESS otherwise
+ *	if all aio_error() values match, the test passed, otherwise it failed
  *
  */
 
-#include <stdio.h>
-#include <sys/types.h>
 #include <unistd.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <aio.h>
 
 #include "posixtest.h"
-#include "tempfile.h"
+#include "aio_test.h"
 
 #define TNAME "aio_cancel/6-1.c"
 
-#define BUF_NB		128
-#define BUF_SIZE	1024
+#define WRITE_COUNT	8
+#define MAX_COMPLETE	3
+#define CANCELED_TASK	5
+
+static int fds[2];
+static struct aiocb aiocb[WRITE_COUNT];
 
 int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
-	char tmpfname[PATH_MAX];
-	int fd;
-	struct aiocb *aiocb[BUF_NB];
 	int i;
-	int in_progress;
 	int gret;
 
 	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
 		return PTS_UNSUPPORTED;
 
-	PTS_GET_TMP_FILENAME(tmpfname, "pts_aio_cancel_6_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));
+	if (setup_aio(TNAME, fds, aiocb, WRITE_COUNT))
 		return PTS_UNRESOLVED;
-	}
-
-	unlink(tmpfname);
 
 	/* create AIO req */
-
-	for (i = 0; i < BUF_NB; i++) {
-		aiocb[i] = calloc(1, sizeof(struct aiocb));
-		if (aiocb[i] == NULL) {
-			printf(TNAME " Error at malloc(): %s\n",
-			       strerror(errno));
-			return PTS_UNRESOLVED;
-		}
-		aiocb[i]->aio_fildes = fd;
-		aiocb[i]->aio_buf = malloc(BUF_SIZE);
-		if (aiocb[i]->aio_buf == NULL) {
-			printf(TNAME " Error at malloc(): %s\n",
-			       strerror(errno));
-			return PTS_UNRESOLVED;
-		}
-		aiocb[i]->aio_nbytes = BUF_SIZE;
-		aiocb[i]->aio_offset = 0;
-		aiocb[i]->aio_sigevent.sigev_notify = SIGEV_NONE;
-
-		if (aio_write(aiocb[i]) == -1) {
+	for (i = 0; i < WRITE_COUNT; i++) {
+		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 the last one queued */
-
-	gret = aio_cancel(fd, aiocb[i - 1]);
+	gret = aio_cancel(fds[0], &aiocb[CANCELED_TASK]);
 
 	if (gret == -1) {
 		printf(TNAME " Error at aio_cancel(): %s\n", strerror(errno));
+		cleanup_aio(fds, aiocb, WRITE_COUNT);
 		return PTS_FAIL;
 	}
 
-	close(fd);
-
-	do {
-		in_progress = 0;
-		for (i = 0; i < BUF_NB; i++) {
-			int ret;
-
-			ret = (aio_error(aiocb[i]));
-
-			if (ret == -1) {
-				printf(TNAME " Error at aio_error(): %s\n",
-				       strerror(errno));
-				return PTS_FAIL;
-			} else if (ret == EINPROGRESS)
-				in_progress = 1;
-			else if (ret == ECANCELED) {
-				if (gret == AIO_CANCELED) {
-					printf("Test PASSED\n");
-					return PTS_PASS;
-				}
-
-				printf(TNAME
-				       " aio_cancel() is not AIO_CANCELED\n");
-				return PTS_FAIL;
-			}
+	if (gret != AIO_CANCELED) {
+		printf(TNAME " Unexpected aio_cancel() return value %d\n",
+			gret);
+		cleanup_aio(fds, aiocb, WRITE_COUNT);
+		return PTS_FAIL;
+	}
+
+	for (i = MAX_COMPLETE; i < WRITE_COUNT; i++) {
+		int exp_ret = (i == CANCELED_TASK) ? ECANCELED : EINPROGRESS;
+		int ret = aio_error(&aiocb[i]);
+
+		if (ret == -1) {
+			printf(TNAME " Error at aio_error(): %s\n",
+				strerror(errno));
+			cleanup_aio(fds, aiocb, WRITE_COUNT);
+			return PTS_FAIL;
 		}
-	} while (in_progress);
 
-	if (gret == AIO_CANCELED) {
-		printf(TNAME
-		       " aio_cancel() is AIO_CANCELED without ECANCELED\n");
-		return PTS_FAIL;
+		if (ret != exp_ret) {
+			printf(TNAME " Bad task #%d result %s",
+				i, strerror(ret));
+			printf(" (expected: %s)\n", strerror(exp_ret));
+			cleanup_aio(fds, aiocb, WRITE_COUNT);
+			return PTS_FAIL;
+		}
 	}
 
-	return PTS_UNRESOLVED;
+	cleanup_aio(fds, aiocb, WRITE_COUNT);
+	printf("Test PASSED\n");
+	return PTS_PASS;
 }
-- 
2.53.0


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

  reply	other threads:[~2026-04-29 14:54 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-29 14:53 [LTP] [PATCH v2 1/2] aio_cancel: Fix incorrect strerror() usage Martin Doucha
2026-04-29 14:53 ` Martin Doucha [this message]
2026-05-06 12:23   ` [LTP] [PATCH v2 2/2] aio_cancel_6-1: Rewrite test Andrea Cervesato via ltp
2026-05-06 16:36   ` Cyril Hrubis
2026-05-07  7:32     ` Andrea Cervesato via ltp
2026-04-29 15:20 ` [LTP] aio_cancel: Fix incorrect strerror() usage linuxtestproject.agent
2026-05-06 12:22 ` [LTP] [PATCH v2 1/2] " Andrea Cervesato via ltp
2026-05-06 15:27 ` Cyril Hrubis
2026-05-07  7:34 ` Andrea Cervesato via ltp

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260429145314.79256-2-mdoucha@suse.cz \
    --to=mdoucha@suse.cz \
    --cc=ltp@lists.linux.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox