From 8b8cc76fa47fe0819e5e52e29c6674e799df646e Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 29 Jun 2002 23:35:02 +0000 Subject: Update. 2002-06-18 Amos Waterland * sysdeps/pthread/aio_cancel.c (aio_cancel): Add check for invalid file descriptor. * sysdeps/pthread/aio_fsync.c (aio_fsync): Add check for invalid fd; add check for fd not open for writing. * sysdeps/pthread/aio_suspend.c (aio_suspend): Add check for completed element(s) and do not suspend thread if so. Patch heavily modified by drepper. * rt/tst-aio7.c: New file. Regression test for problems which the above three changes fix. * rt/Makefile (tests): Add tst-aio7. * rt/tst-aio6.c: Fix comment. --- sysdeps/pthread/aio_cancel.c | 9 ++++- sysdeps/pthread/aio_fsync.c | 14 ++++++- sysdeps/pthread/aio_suspend.c | 92 ++++++++++++++++++++++++++----------------- 3 files changed, 75 insertions(+), 40 deletions(-) (limited to 'sysdeps') diff --git a/sysdeps/pthread/aio_cancel.c b/sysdeps/pthread/aio_cancel.c index c2fe6da..d62586b 100644 --- a/sysdeps/pthread/aio_cancel.c +++ b/sysdeps/pthread/aio_cancel.c @@ -1,5 +1,5 @@ /* Cancel requests associated with given file descriptor. - Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -43,6 +43,13 @@ aio_cancel (fildes, aiocbp) struct requestlist *req = NULL; int result = AIO_ALLDONE; + /* If fildes is invalid, error. */ + if (fcntl (fildes, F_GETFL) < 0) + { + __set_errno (EBADF); + return -1; + } + /* Request the mutex. */ pthread_mutex_lock (&__aio_requests_mutex); diff --git a/sysdeps/pthread/aio_fsync.c b/sysdeps/pthread/aio_fsync.c index 17f4351..4c90d69 100644 --- a/sysdeps/pthread/aio_fsync.c +++ b/sysdeps/pthread/aio_fsync.c @@ -1,5 +1,5 @@ /* Synchronize I/O in given file descriptor. - Copyright (C) 1997, 1999 Free Software Foundation, Inc. + Copyright (C) 1997, 1999, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -36,12 +36,22 @@ int aio_fsync (int op, struct aiocb *aiocbp) { - if (op != O_DSYNC && op != O_SYNC) + int flags; + + if (op != O_DSYNC && __builtin_expect (op != O_SYNC, 0)) { __set_errno (EINVAL); return -1; } + flags = fcntl (aiocbp->aio_fildes, F_GETFL); + if (__builtin_expect (flags == -1, 0) + || __builtin_expect ((flags & (O_RDWR | O_WRONLY)) == 0, 0)) + { + __set_errno (EBADF); + return -1; + } + return (__aio_enqueue_request ((aiocb_union *) aiocbp, op == O_SYNC ? LIO_SYNC : LIO_DSYNC) == NULL ? -1 : 0); diff --git a/sysdeps/pthread/aio_suspend.c b/sysdeps/pthread/aio_suspend.c index f9c5709..8def01c 100644 --- a/sysdeps/pthread/aio_suspend.c +++ b/sysdeps/pthread/aio_suspend.c @@ -1,5 +1,5 @@ /* Suspend until termination of a requests. - Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -29,7 +29,9 @@ /* And undo the hack. */ #undef aio_suspend64 +#include #include +#include #include #include @@ -48,7 +50,7 @@ aio_suspend (list, nent, timeout) int cnt; int result = 0; int dummy; - int none = 1; + bool any = false; /* Request the mutex. */ pthread_mutex_lock (&__aio_requests_mutex); @@ -56,24 +58,34 @@ aio_suspend (list, nent, timeout) /* There is not yet a finished request. Signal the request that we are working for it. */ for (cnt = 0; cnt < nent; ++cnt) - if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS) + if (list[cnt] != NULL) { - requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]); - - if (requestlist[cnt] != NULL) + if (list[cnt]->__error_code == EINPROGRESS) { - waitlist[cnt].cond = &cond; - waitlist[cnt].next = requestlist[cnt]->waiting; - waitlist[cnt].counterp = &dummy; - waitlist[cnt].sigevp = NULL; - waitlist[cnt].caller_pid = 0; /* Not needed. */ - requestlist[cnt]->waiting = &waitlist[cnt]; - none = 0; + requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]); + + if (requestlist[cnt] != NULL) + { + waitlist[cnt].cond = &cond; + waitlist[cnt].next = requestlist[cnt]->waiting; + waitlist[cnt].counterp = &dummy; + waitlist[cnt].sigevp = NULL; + waitlist[cnt].caller_pid = 0; /* Not needed. */ + requestlist[cnt]->waiting = &waitlist[cnt]; + any = true; + } + else + /* We will never suspend. */ + break; } + else + /* We will never suspend. */ + break; } - /* If there is a not finished request wait for it. */ - if (!none) + /* If there is no finished request wait for it. In any case we have + to dequeue the requests if we enqueued them. */ + if (any) { int oldstate; @@ -82,39 +94,45 @@ aio_suspend (list, nent, timeout) which we must remove. So defer cancelation for now. */ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); - if (timeout == NULL) - result = pthread_cond_wait (&cond, &__aio_requests_mutex); - else + /* Only if none of the entries is NULL or finished to be wait. */ + if (cnt == nent) { - /* We have to convert the relative timeout value into an - absolute time value with pthread_cond_timedwait expects. */ - struct timeval now; - struct timespec abstime; - - __gettimeofday (&now, NULL); - abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000; - abstime.tv_sec = timeout->tv_sec + now.tv_sec; - if (abstime.tv_nsec >= 1000000000) + if (timeout == NULL) + result = pthread_cond_wait (&cond, &__aio_requests_mutex); + else { - abstime.tv_nsec -= 1000000000; - abstime.tv_sec += 1; + /* We have to convert the relative timeout value into an + absolute time value with pthread_cond_timedwait expects. */ + struct timeval now; + struct timespec abstime; + + __gettimeofday (&now, NULL); + abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000; + abstime.tv_sec = timeout->tv_sec + now.tv_sec; + if (abstime.tv_nsec >= 1000000000) + { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec += 1; + } + + result = pthread_cond_timedwait (&cond, &__aio_requests_mutex, + &abstime); } - - result = pthread_cond_timedwait (&cond, &__aio_requests_mutex, - &abstime); } /* Now remove the entry in the waiting list for all requests which didn't terminate. */ - for (cnt = 0; cnt < nent; ++cnt) - if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS - && requestlist[cnt] != NULL) + while (cnt-- > 0) + if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS) { - struct waitlist **listp = &requestlist[cnt]->waiting; + struct waitlist **listp; + + assert (requestlist[cnt] != NULL); /* There is the chance that we cannot find our entry anymore. This could happen if the request terminated and restarted again. */ + listp = &requestlist[cnt]->waiting; while (*listp != NULL && *listp != &waitlist[cnt]) listp = &(*listp)->next; @@ -126,7 +144,7 @@ aio_suspend (list, nent, timeout) pthread_setcancelstate (oldstate, NULL); /* Release the conditional variable. */ - if (pthread_cond_destroy (&cond) != 0) + if (__builtin_expect (pthread_cond_destroy (&cond) != 0, 0)) /* This must never happen. */ abort (); -- cgit v1.1