summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2006-03-01 23:41:47 +0000
committerdavidxu <davidxu@FreeBSD.org>2006-03-01 23:41:47 +0000
commita8886a11b7bccb06c3b2682c99aabe7d8c293022 (patch)
tree6e37c883ec4464af63558cb828951b77ce43e54f
parent5d292c8fb4660045bd1a0d80bbb7337fd5ab03d7 (diff)
downloadFreeBSD-src-a8886a11b7bccb06c3b2682c99aabe7d8c293022.zip
FreeBSD-src-a8886a11b7bccb06c3b2682c99aabe7d8c293022.tar.gz
1. Fix a race in aio_return.
2. Save and restore syscall errno correctly. 3. Style fix.
-rw-r--r--lib/librt/aio.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/lib/librt/aio.c b/lib/librt/aio.c
index 48dba64..0ea0d51 100644
--- a/lib/librt/aio.c
+++ b/lib/librt/aio.c
@@ -71,7 +71,7 @@ aio_io(struct aiocb *iocb, int (*sysfunc)(struct aiocb *iocb))
{
struct sigev_node *sn;
struct sigevent saved_ev;
- int ret;
+ int ret, err;
if (iocb->aio_sigevent.sigev_notify != SIGEV_THREAD) {
ret = sysfunc(iocb);
@@ -104,9 +104,11 @@ aio_io(struct aiocb *iocb, int (*sysfunc)(struct aiocb *iocb))
iocb->aio_sigevent = saved_ev;
if (ret != 0) {
+ err = errno;
__sigev_list_lock();
__sigev_delete_node(sn);
__sigev_list_unlock();
+ errno = err;
}
return (ret);
}
@@ -114,25 +116,30 @@ aio_io(struct aiocb *iocb, int (*sysfunc)(struct aiocb *iocb))
int
__aio_read(struct aiocb *iocb)
{
+
return aio_io(iocb, &__sys_aio_read);
}
int
__aio_write(struct aiocb *iocb)
{
+
return aio_io(iocb, &__sys_aio_write);
}
int
__aio_waitcomplete(struct aiocb **iocbp, struct timespec *timeout)
{
+ int err;
int ret = __sys_aio_waitcomplete(iocbp, timeout);
if (*iocbp) {
if ((*iocbp)->aio_sigevent.sigev_notify == SIGEV_THREAD) {
+ err = errno;
__sigev_list_lock();
__sigev_delete(SI_ASYNCIO, (sigev_id_t)(*iocbp));
__sigev_list_unlock();
+ errno = err;
}
}
@@ -142,15 +149,14 @@ __aio_waitcomplete(struct aiocb **iocbp, struct timespec *timeout)
int
__aio_return(struct aiocb *iocb)
{
- int ret = __sys_aio_return(iocb);
- int err = __sys_aio_error(iocb);
- if (err != EINPROGRESS &&
- iocb->aio_sigevent.sigev_notify == SIGEV_THREAD) {
+ if (iocb->aio_sigevent.sigev_notify == SIGEV_THREAD) {
+ if (__sys_aio_error(iocb) == EINPROGRESS)
+ return (EINPROGRESS);
__sigev_list_lock();
__sigev_delete(SI_ASYNCIO, (sigev_id_t)iocb);
__sigev_list_unlock();
}
- return (ret);
+ return __sys_aio_return(iocb);
}
OpenPOWER on IntegriCloud