diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | rt/Makefile | 2 | ||||
-rw-r--r-- | rt/tst-aio10.c | 119 | ||||
-rw-r--r-- | sysdeps/pthread/lio_listio.c | 5 |
4 files changed, 126 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog index 6cebfc3c8f..b0c6aa8fd2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,8 +7,9 @@ * sysdeps/pthread/aio_suspend.c [!DONT_USE_BOOTSTRAP_MAP]: Don't use condvar, use AIO_MISC_WAIT. * sysdeps/pthread/lio_listio.c: Likewise. - * rt/Makefile (tests): Add aio_suspend. + * rt/Makefile (tests): Add tst-aio9 and tst-aio10. * rt/tst-aio9.c: New file. + * rt/tst-aio10.c: New file. * rt/tst-aio3.c: The thread is now supposed to be created. diff --git a/rt/Makefile b/rt/Makefile index 4f7d5f9d40..f8487975dd 100644 --- a/rt/Makefile +++ b/rt/Makefile @@ -43,7 +43,7 @@ librt-routines = $(aio-routines) \ tests := tst-shm tst-clock tst-clock_nanosleep tst-timer tst-timer2 \ tst-aio tst-aio64 tst-aio2 tst-aio3 tst-aio4 tst-aio5 tst-aio6 \ - tst-aio7 tst-aio8 tst-aio9 \ + tst-aio7 tst-aio8 tst-aio9 tst-aio10 \ tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \ tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \ tst-timer3 tst-timer4 tst-timer5 \ diff --git a/rt/tst-aio10.c b/rt/tst-aio10.c new file mode 100644 index 0000000000..6e8f7b78c0 --- /dev/null +++ b/rt/tst-aio10.c @@ -0,0 +1,119 @@ +#include <aio.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <pthread.h> +#include <unistd.h> + +static pthread_barrier_t b; +static pthread_t main_thread; +static int flag; + + +static void * +tf (void *arg) +{ + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("child: barrier_wait failed"); + exit (1); + } + + /* There is unfortunately no other way to try to make sure the other + thread reached the aio_suspend call. This test could fail on + highly loaded machines. */ + sleep (2); + + pthread_kill (main_thread, SIGUSR1); + + while (1) + sleep (1000); + + return NULL; +} + + +static void +sh (int sig) +{ + flag = 1; +} + + +static int +do_test (void) +{ + main_thread = pthread_self (); + + struct sigaction sa; + + sa.sa_handler = sh; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + + if (sigaction (SIGUSR1, &sa, NULL) != 0) + { + puts ("sigaction failed"); + return 1; + } + + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init"); + return 1; + } + + int fds[2]; + if (pipe (fds) != 0) + { + puts ("pipe failed"); + return 1; + } + + char buf[42]; + struct aiocb req; + req.aio_fildes = fds[0]; + req.aio_lio_opcode = LIO_READ; + req.aio_reqprio = 0; + req.aio_offset = 0; + req.aio_buf = buf; + req.aio_nbytes = sizeof (buf); + req.aio_sigevent.sigev_notify = SIGEV_NONE; + + pthread_t th; + if (pthread_create (&th, NULL, tf, NULL) != 0) + { + puts ("create failed"); + return 1; + } + + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("parent: barrier_wait failed"); + exit (1); + } + + struct aiocb *list[1]; + list[0] = &req; + + e = lio_listio (LIO_WAIT, list, 1, NULL); + if (e != -1) + { + puts ("lio_listio succeeded"); + return 1; + } + if (errno != EINTR) + { + printf ("lio_listio did not return EINTR: %d (%d = %m)\n", e, errno); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#define TIMEOUT 5 +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/lio_listio.c b/sysdeps/pthread/lio_listio.c index 39187f3025..c652404ae2 100644 --- a/sysdeps/pthread/lio_listio.c +++ b/sysdeps/pthread/lio_listio.c @@ -172,7 +172,10 @@ lio_listio_internal (int mode, struct aiocb *const list[], int nent, /* If any of the I/O requests failed, return -1 and set errno. */ if (result != 0) - __set_errno (EIO); + { + __set_errno (result == EINTR ? EINTR : EIO); + result = -1; + } } else { |