(root)/
glibc-2.38/
rt/
tst-aio7.c
       1  /* Test for AIO POSIX compliance.
       2     Copyright (C) 2001-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <aio.h>
      20  #include <error.h>
      21  #include <errno.h>
      22  #include <fcntl.h>
      23  #include <stdio.h>
      24  #include <stdlib.h>
      25  #include <unistd.h>
      26  
      27  
      28  #define TEST_FUNCTION do_test ()
      29  static int
      30  do_test (void)
      31  {
      32    int result = 0;
      33    int piped[2];
      34  
      35    /* Make a pipe that we will never write to, so we can block reading it.  */
      36    if (pipe (piped) < 0)
      37      {
      38        perror ("pipe");
      39        return 1;
      40      }
      41  
      42    /* Test for aio_cancel() detecting invalid file descriptor.  */
      43    {
      44      struct aiocb cb;
      45      int fd = -1;
      46  
      47      cb.aio_fildes = fd;
      48      cb.aio_offset = 0;
      49      cb.aio_buf = NULL;
      50      cb.aio_nbytes = 0;
      51      cb.aio_reqprio = 0;
      52      cb.aio_sigevent.sigev_notify = SIGEV_NONE;
      53  
      54      errno = 0;
      55  
      56      /* Case one: invalid fds that match.  */
      57      if (aio_cancel (fd, &cb) != -1 || errno != EBADF)
      58        {
      59  	if (errno == ENOSYS)
      60  	  {
      61  	    puts ("no aio support in this configuration");
      62  	    return 0;
      63  	  }
      64  
      65  	puts ("aio_cancel( -1, {-1..} ) did not return -1 or errno != EBADF");
      66  	++result;
      67        }
      68  
      69      cb.aio_fildes = -2;
      70      errno = 0;
      71  
      72      /* Case two: invalid fds that do not match; just print warning.  */
      73      if (aio_cancel (fd, &cb) != -1 || errno != EBADF)
      74        puts ("aio_cancel( -1, {-2..} ) did not return -1 or errno != EBADF");
      75    }
      76  
      77    /* Test for aio_fsync() detecting bad fd.  */
      78    {
      79      struct aiocb cb;
      80      int fd = -1;
      81  
      82      cb.aio_fildes = fd;
      83      cb.aio_offset = 0;
      84      cb.aio_buf = NULL;
      85      cb.aio_nbytes = 0;
      86      cb.aio_reqprio = 0;
      87      cb.aio_sigevent.sigev_notify = SIGEV_NONE;
      88  
      89      errno = 0;
      90  
      91      /* Case one: invalid fd.  */
      92      if (aio_fsync (O_SYNC, &cb) != -1 || errno != EBADF)
      93        {
      94  	puts ("aio_fsync( op, {-1..} ) did not return -1 or errno != EBADF");
      95  	++result;
      96        }
      97    }
      98  
      99    /* Test for aio_suspend() suspending even if completed elements in list.  */
     100    {
     101  #define BYTES 8
     102      const int ELEMS = 2;
     103      int i, r, fd;
     104      static char buff[BYTES];
     105      char name[] = "/tmp/aio7.XXXXXX";
     106      struct timespec timeout;
     107      static struct aiocb cb0, cb1;
     108      struct aiocb *list[ELEMS];
     109  
     110      fd = mkstemp (name);
     111      if (fd < 0)
     112        error (1, errno, "creating temp file");
     113  
     114      if (unlink (name))
     115        error (1, errno, "unlinking temp file");
     116  
     117      if (write (fd, "01234567", BYTES) != BYTES)
     118        error (1, errno, "writing to temp file");
     119  
     120      cb0.aio_fildes = fd;
     121      cb0.aio_offset = 0;
     122      cb0.aio_buf = buff;
     123      cb0.aio_nbytes = BYTES;
     124      cb0.aio_reqprio = 0;
     125      cb0.aio_sigevent.sigev_notify = SIGEV_NONE;
     126  
     127      r = aio_read (&cb0);
     128      if (r != 0)
     129        error (1, errno, "reading from file");
     130  
     131      while (aio_error (&(cb0)) == EINPROGRESS)
     132        usleep (10);
     133  
     134      for (i = 0; i < BYTES; i++)
     135        printf ("%c ", buff[i]);
     136      printf ("\n");
     137  
     138      /* At this point, the first read is completed, so start another one on
     139         the read half of a pipe on which nothing will be written.  */
     140      cb1.aio_fildes = piped[0];
     141      cb1.aio_offset = 0;
     142      cb1.aio_buf = buff;
     143      cb1.aio_nbytes = BYTES;
     144      cb1.aio_reqprio = 0;
     145      cb1.aio_sigevent.sigev_notify = SIGEV_NONE;
     146  
     147      r = aio_read (&cb1);
     148      if (r != 0)
     149        error (1, errno, "reading from file");
     150  
     151      /* Now call aio_suspend() with the two reads.  It should return
     152       * immediately according to the POSIX spec.
     153       */
     154      list[0] = &cb0;
     155      list[1] = &cb1;
     156      timeout.tv_sec = 3;
     157      timeout.tv_nsec = 0;
     158      r = aio_suspend ((const struct aiocb * const *) list, ELEMS, &timeout);
     159  
     160      if (r == -1 && errno == EAGAIN)
     161        {
     162  	puts ("aio_suspend([done,blocked],2,3) suspended thread");
     163  	++result;
     164        }
     165  
     166      /* Note that CB1 is still pending, and so cannot be an auto variable.
     167         Thus we also test that exiting with an outstanding request works.  */
     168    }
     169  
     170    return result;
     171  }
     172  
     173  #include "../test-skeleton.c"