[LTP] [PATCH v3] aio_cancel_7-1: Write into a socket

Li Wang liwang@redhat.com
Mon Aug 25 05:07:17 CEST 2025


On Fri, Aug 22, 2025 at 9:57 PM Martin Doucha <mdoucha@suse.cz> wrote:

> 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.
>
> Also add another case to the final result check because the aio_cancel()
> call may happen between one write finishing and another write starting.
> Then the cancel will be successful and all non-zero task results will be
> ECANCELED.
>
> Signed-off-by: Martin Doucha <mdoucha@suse.cz>
> ---
>
> Changes since v1: Rebased to current master.
>
> Changes since v2:
> - Changed argsize from unsigned int to socklen_t
> - Improved test cleanup using a helper function
>
>  .../conformance/interfaces/aio_cancel/7-1.c   | 85 +++++++++++++------
>  1 file changed, 57 insertions(+), 28 deletions(-)
>
> diff --git
> a/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/7-1.c
> b/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/7-1.c
> index 34b263245..9ab72da87 100644
> ---
> a/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/7-1.c
> +++
> b/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/7-1.c
>

We need to update the code comments as well:

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (c) 2004, Bull SA. All rights reserved.
 * Copyright (c) Linux Test Project, 2025
 */

/*
 * Assertion:
 *    aio_cancel() shall return AIO_NOTCANCELED if at least one requested
 *    operation cannot be canceled because it is already in progress.
 *
 * Method:
 *    1. Queue multiple aio_write() requests to a given file descriptor.
 *    2. Call aio_cancel() to attempt canceling all operations.
 *    3. Check each operation's result using aio_error():
 *       - If aio_error() returns EINPROGRESS but aio_cancel() did not
return
 *         AIO_NOTCANCELED, the test FAILS.
 *       - If aio_error() returns 0 (success) and aio_cancel() returned
 *         AIO_NOTCANCELED, the test PASSES.
 *       - Otherwise, the test result is UNRESOLVED.
 */



> @@ -29,71 +29,90 @@
>  #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 <sys/socket.h>
>
>  #include "posixtest.h"
> -#include "tempfile.h"
>
>  #define TNAME "aio_cancel/7-1.c"
>
> -#define BUF_NB         128
> -#define BUF_SIZE       1024
> +#define BUF_NB         8
> +
> +static int fds[2];
> +static struct aiocb *aiocb[BUF_NB];
> +
> +static void cleanup(void)
> +{
> +       int i;
> +
> +       close(fds[1]);
> +       close(fds[0]);
> +
> +       for (i = 0; i < BUF_NB; i++)
> +               free((void *)aiocb[i]->aio_buf);
>

Agree, and maybe do something further:

for (i = 0; i < BUF_NB; i++) {
        if (aiocb[i]) {
                if (aiocb[i]->aio_buf)
                        free((void *)aiocb[i]->aio_buf);
                free(aiocb[i]);
                aiocb[i] = NULL;
        }
}



> +}
>
>  int main(void)
>  {
> -       char tmpfname[PATH_MAX];
> -       int fd;
> -       struct aiocb *aiocb[BUF_NB];
>         int i;
>         int in_progress;
>         int gret;
> +       int bufsize;
> +       socklen_t argsize = sizeof(bufsize);
>
>         if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
>                 return PTS_UNSUPPORTED;
>
> -       PTS_GET_TMP_FILENAME(tmpfname, "pts_aio_cancel_7_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));
> +       gret = socketpair(AF_UNIX, SOCK_DGRAM, 0, fds);
> +       if (gret == -1) {
> +               printf(TNAME " Error creating sockets(): %s\n",
> +                       strerror(errno));
> +               return PTS_UNRESOLVED;
> +       }
> +
> +       gret = getsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &bufsize,
> &argsize);
> +       if (gret == -1) {
> +               printf(TNAME " Error reading socket buffer size: %s\n",
> +                       strerror(errno));
> +               cleanup();
>                 return PTS_UNRESOLVED;
>         }
>
> -       unlink(tmpfname);
> +       /* Socket buffer size is twice the maximum message size */
> +       bufsize /= 2;
>
>         /* 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",
> +                       printf(TNAME " Error at calloc(): %s\n",
>                                strerror(errno));
> -                       close(fd);
> +                       cleanup();
>                         return PTS_UNRESOLVED;
>                 }
>
> -               aiocb[i]->aio_fildes = fd;
> -               aiocb[i]->aio_buf = malloc(BUF_SIZE);
> +               aiocb[i]->aio_fildes = fds[0];
> +               aiocb[i]->aio_buf = malloc(bufsize);
>
>                 if (aiocb[i]->aio_buf == NULL) {
>                         printf(TNAME " Error at malloc(): %s\n",
>                                strerror(errno));
> -                       close(fd);
> +                       cleanup();
>                         return PTS_UNRESOLVED;
>                 }
>
> -               aiocb[i]->aio_nbytes = BUF_SIZE;
> +               aiocb[i]->aio_nbytes = bufsize;
>                 aiocb[i]->aio_offset = 0;
>                 aiocb[i]->aio_sigevent.sigev_notify = SIGEV_NONE;
>
>                 if (aio_write(aiocb[i]) == -1) {
>                         printf(TNAME " loop %d: Error at aio_write():
> %s\n",
>                                i, strerror(errno));
> -                       close(fd);
> +                       cleanup();
>                         return PTS_FAIL;
>                 }
>         }
> @@ -101,10 +120,10 @@ int main(void)
>         /* try to cancel all
>          * we hope to have enough time to cancel at least one
>          */
> -       gret = aio_cancel(fd, NULL);
> +       gret = aio_cancel(fds[0], NULL);
>         if (gret == -1) {
>                 printf(TNAME " Error at aio_cancel(): %s\n",
> strerror(errno));
> -               close(fd);
> +               cleanup();
>                 return PTS_FAIL;
>         }
>
> @@ -117,9 +136,8 @@ int main(void)
>                         case -1:
>                                 printf(TNAME " Error at aio_error(): %s\n",
>                                        strerror(errno));
> -                               close(fd);
> +                               cleanup();
>                                 return PTS_FAIL;
> -                               break;
>                         case EINPROGRESS:
>                                 /* at this point, all operations should be:
>                                  *    canceled
> @@ -130,12 +148,24 @@ int main(void)
>                                         printf(TNAME
>                                                " Error at aio_error():
> %s\n",
>                                                strerror(errno));
> -                                       close(fd);
> +                                       cleanup();
>                                         return PTS_FAIL;
>                                 }
>
>                                 in_progress = 1;
>                                 break;
> +                       case ECANCELED:
> +                               /* aio_cancel() happened between one
> +                                * write finishing and another starting.
> +                                * aio_cancel() returned AIO_CANCELED
> +                                * and the first non-zero result is
> ECANCELED.
> +                                */
> +                               if (gret == AIO_CANCELED) {
> +                                       printf("Test PASSED\n");
> +                                       cleanup();
> +                                       return PTS_PASS;
> +                               }
> +                               break;
>                         case 0:
>                                 /* we seek one not canceled and check why.
>                                  * (perhaps) it has not been canceled
> @@ -144,7 +174,7 @@ int main(void)
>                                  */
>                                 if (gret == AIO_NOTCANCELED) {
>                                         printf("Test PASSED\n");
> -                                       close(fd);
> +                                       cleanup();
>                                         return PTS_PASS;
>                                 }
>                                 break;
> @@ -152,7 +182,6 @@ int main(void)
>                 }
>         } while (in_progress);
>
> -       close(fd);
> -
> +       cleanup();
>         return PTS_UNRESOLVED;
>  }
> --
> 2.50.1
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
>
>

-- 
Regards,
Li Wang


More information about the ltp mailing list