Back to index

glibc  2.9
tst-aio7.c
Go to the documentation of this file.
00001 /* Test for AIO POSIX compliance.
00002    Copyright (C) 2001,02, 03 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <aio.h>
00021 #include <error.h>
00022 #include <errno.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <unistd.h>
00026 
00027 
00028 /* We might wait for 3 seconds, so increase timeout to 10 seconds.  */
00029 #define TIMEOUT 10
00030 
00031 
00032 #define TEST_FUNCTION do_test ()
00033 static int
00034 do_test (void)
00035 {
00036   int result = 0;
00037   int piped[2];
00038 
00039   /* Make a pipe that we will never write to, so we can block reading it.  */
00040   if (pipe (piped) < 0)
00041     {
00042       perror ("pipe");
00043       return 1;
00044     }
00045 
00046   /* Test for aio_cancel() detecting invalid file descriptor.  */
00047   {
00048     struct aiocb cb;
00049     int fd = -1;
00050 
00051     cb.aio_fildes = fd;
00052     cb.aio_offset = 0;
00053     cb.aio_buf = NULL;
00054     cb.aio_nbytes = 0;
00055     cb.aio_reqprio = 0;
00056     cb.aio_sigevent.sigev_notify = SIGEV_NONE;
00057 
00058     errno = 0;
00059 
00060     /* Case one: invalid fds that match.  */
00061     if (aio_cancel (fd, &cb) != -1 || errno != EBADF)
00062       {
00063        if (errno == ENOSYS)
00064          {
00065            puts ("no aio support in this configuration");
00066            return 0;
00067          }
00068 
00069        puts ("aio_cancel( -1, {-1..} ) did not return -1 or errno != EBADF");
00070        ++result;
00071       }
00072 
00073     cb.aio_fildes = -2;
00074     errno = 0;
00075 
00076     /* Case two: invalid fds that do not match; just print warning.  */
00077     if (aio_cancel (fd, &cb) != -1 || errno != EBADF)
00078       puts ("aio_cancel( -1, {-2..} ) did not return -1 or errno != EBADF");
00079   }
00080 
00081   /* Test for aio_fsync() detecting bad fd, and fd not open for writing.  */
00082   {
00083     struct aiocb cb;
00084     int fd = -1;
00085 
00086     cb.aio_fildes = fd;
00087     cb.aio_offset = 0;
00088     cb.aio_buf = NULL;
00089     cb.aio_nbytes = 0;
00090     cb.aio_reqprio = 0;
00091     cb.aio_sigevent.sigev_notify = SIGEV_NONE;
00092 
00093     errno = 0;
00094 
00095     /* Case one: invalid fd.  */
00096     if (aio_fsync (O_SYNC, &cb) != -1 || errno != EBADF)
00097       {
00098        puts ("aio_fsync( op, {-1..} ) did not return -1 or errno != EBADF");
00099        ++result;
00100       }
00101 
00102     if ((fd = open ("/dev/null", O_RDONLY)) < 0)
00103       error (1, errno, "opening /dev/null");
00104 
00105     cb.aio_fildes = fd;
00106     errno = 0;
00107 
00108     /* Case two: valid fd but open for read only.  */
00109     if (aio_fsync (O_SYNC, &cb) != -1 || errno != EBADF)
00110       {
00111        puts ("aio_fsync( op, {RO..} ) did not return -1 or errno != EBADF");
00112        ++result;
00113       }
00114 
00115     close (fd);
00116   }
00117 
00118   /* Test for aio_suspend() suspending even if completed elements in list.  */
00119   {
00120 #define BYTES 8
00121     const int ELEMS = 2;
00122     int i, r, fd;
00123     static char buff[BYTES];
00124     char name[] = "/tmp/aio7.XXXXXX";
00125     struct timespec timeout;
00126     static struct aiocb cb0, cb1;
00127     struct aiocb *list[ELEMS];
00128 
00129     fd = mkstemp (name);
00130     if (fd < 0)
00131       error (1, errno, "creating temp file");
00132 
00133     if (unlink (name))
00134       error (1, errno, "unlinking temp file");
00135 
00136     if (write (fd, "01234567", BYTES) != BYTES)
00137       error (1, errno, "writing to temp file");
00138 
00139     cb0.aio_fildes = fd;
00140     cb0.aio_offset = 0;
00141     cb0.aio_buf = buff;
00142     cb0.aio_nbytes = BYTES;
00143     cb0.aio_reqprio = 0;
00144     cb0.aio_sigevent.sigev_notify = SIGEV_NONE;
00145 
00146     r = aio_read (&cb0);
00147     if (r != 0)
00148       error (1, errno, "reading from file");
00149 
00150     while (aio_error (&(cb0)) == EINPROGRESS)
00151       usleep (10);
00152 
00153     for (i = 0; i < BYTES; i++)
00154       printf ("%c ", buff[i]);
00155     printf ("\n");
00156 
00157     /* At this point, the first read is completed, so start another one on
00158        the read half of a pipe on which nothing will be written.  */
00159     cb1.aio_fildes = piped[0];
00160     cb1.aio_offset = 0;
00161     cb1.aio_buf = buff;
00162     cb1.aio_nbytes = BYTES;
00163     cb1.aio_reqprio = 0;
00164     cb1.aio_sigevent.sigev_notify = SIGEV_NONE;
00165 
00166     r = aio_read (&cb1);
00167     if (r != 0)
00168       error (1, errno, "reading from file");
00169 
00170     /* Now call aio_suspend() with the two reads.  It should return
00171      * immediately according to the POSIX spec.
00172      */
00173     list[0] = &cb0;
00174     list[1] = &cb1;
00175     timeout.tv_sec = 3;
00176     timeout.tv_nsec = 0;
00177     r = aio_suspend ((const struct aiocb * const *) list, ELEMS, &timeout);
00178 
00179     if (r == -1 && errno == EAGAIN)
00180       {
00181        puts ("aio_suspend([done,blocked],2,3) suspended thread");
00182        ++result;
00183       }
00184 
00185     /* Note that CB1 is still pending, and so cannot be an auto variable.
00186        Thus we also test that exiting with an outstanding request works.  */
00187   }
00188 
00189   return result;
00190 }
00191 
00192 #include "../test-skeleton.c"