From 0b9cfd5991f71854b5b632f246fa6748372bf806 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 15 Aug 1999 20:28:48 +0000 Subject: [PATCH] Update from main branch. --- rt/aio_misc.c | 22 ++++++++++++++++++++++ rt/aio_misc.h | 15 ++++++++++++--- rt/aio_notify.c | 11 ++++++----- rt/aio_suspend.c | 3 ++- rt/lio_listio.c | 17 +++++++++++++++-- rt/lio_listio64.c | 17 +++++++++++++++-- sysdeps/generic/aio_sigqueue.c | 4 ++-- sysdeps/unix/sysv/linux/aio_sigqueue.c | 7 ++++--- 8 files changed, 78 insertions(+), 18 deletions(-) diff --git a/rt/aio_misc.c b/rt/aio_misc.c index ba0c9d47cf3..fa3c75c150f 100644 --- a/rt/aio_misc.c +++ b/rt/aio_misc.c @@ -265,6 +265,8 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation) return NULL; } newp->aiocbp = aiocbp; + newp->caller_pid = (aiocbp->aiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL + ? getpid () : 0); newp->waiting = NULL; aiocbp->aiocb.__abs_prio = prio; @@ -435,6 +437,16 @@ handle_fildes_io (void *arg) (void *) aiocbp->aiocb.aio_buf, aiocbp->aiocb.aio_nbytes, aiocbp->aiocb.aio_offset)); + + if (aiocbp->aiocb.__return_value == -1 && errno == ESPIPE) + /* The Linux kernel is different from others. It returns + ESPIPE if using pread on a socket. Other platforms + simply ignore the offset parameter and behave like + read. */ + aiocbp->aiocb.__return_value = + TEMP_FAILURE_RETRY (read (fildes, + (void *) aiocbp->aiocb64.aio_buf, + aiocbp->aiocb64.aio_nbytes)); } else if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_WRITE) { @@ -450,6 +462,16 @@ handle_fildes_io (void *arg) (const void *) aiocbp->aiocb.aio_buf, aiocbp->aiocb.aio_nbytes, aiocbp->aiocb.aio_offset)); + + if (aiocbp->aiocb.__return_value == -1 && errno == ESPIPE) + /* The Linux kernel is different from others. It returns + ESPIPE if using pwrite on a socket. Other platforms + simply ignore the offset parameter and behave like + write. */ + aiocbp->aiocb.__return_value = + TEMP_FAILURE_RETRY (write (fildes, + (void *) aiocbp->aiocb64.aio_buf, + aiocbp->aiocb64.aio_nbytes)); } else if (aiocbp->aiocb.aio_lio_opcode == LIO_DSYNC) aiocbp->aiocb.__return_value = TEMP_FAILURE_RETRY (fdatasync (fildes)); diff --git a/rt/aio_misc.h b/rt/aio_misc.h index af8e2479baa..e3c93bef367 100644 --- a/rt/aio_misc.h +++ b/rt/aio_misc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -50,6 +50,9 @@ struct waitlist volatile int *counterp; /* The next field is used in asynchronous `lio_listio' operations. */ struct sigevent *sigevp; + /* XXX See requestlist, it's used to work around the broken signal + handling in Linux. */ + pid_t caller_pid; }; @@ -76,6 +79,10 @@ struct requestlist /* Pointer to the actual data. */ aiocb_union *aiocbp; + /* PID of the initiator thread. + XXX This is only necessary for the broken signal handling on Linux. */ + pid_t caller_pid; + /* List of waiting processes. */ struct waitlist *waiting; }; @@ -104,9 +111,11 @@ extern void __aio_free_request (struct requestlist *req) internal_function; extern void __aio_notify (struct requestlist *req) internal_function; /* Notify initiator of request. */ -extern int __aio_notify_only (struct sigevent *sigev) internal_function; +extern int __aio_notify_only (struct sigevent *sigev, pid_t caller_pid) + internal_function; /* Send the signal. */ -extern int __aio_sigqueue (int sig, const union sigval val) internal_function; +extern int __aio_sigqueue (int sig, const union sigval val, pid_t caller_pid) + internal_function; #endif /* aio_misc.h */ diff --git a/rt/aio_notify.c b/rt/aio_notify.c index 8c57d72e9bc..54e9959bfad 100644 --- a/rt/aio_notify.c +++ b/rt/aio_notify.c @@ -1,5 +1,5 @@ /* Notify initiator of AIO request. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -25,7 +25,7 @@ int internal_function -__aio_notify_only (struct sigevent *sigev) +__aio_notify_only (struct sigevent *sigev, pid_t caller_pid) { int result = 0; @@ -51,7 +51,8 @@ __aio_notify_only (struct sigevent *sigev) } else if (sigev->sigev_notify == SIGEV_SIGNAL) /* We have to send a signal. */ - if (__aio_sigqueue (sigev->sigev_signo, sigev->sigev_value) < 0) + if (__aio_sigqueue (sigev->sigev_signo, sigev->sigev_value, caller_pid) + < 0) result = -1; return result; @@ -65,7 +66,7 @@ __aio_notify (struct requestlist *req) struct waitlist *waitlist; struct aiocb *aiocbp = &req->aiocbp->aiocb; - if (__aio_notify_only (&aiocbp->aio_sigevent) != 0) + if (__aio_notify_only (&aiocbp->aio_sigevent, req->caller_pid) != 0) { /* XXX What shall we do if already an error is set by read/write/fsync? */ @@ -89,7 +90,7 @@ __aio_notify (struct requestlist *req) this request is the last one, send the signal. */ if (*waitlist->counterp == 0) { - __aio_notify_only (waitlist->sigevp); + __aio_notify_only (waitlist->sigevp, waitlist->caller_pid); /* This is tricky. See lio_listio.c for the reason why this works. */ free ((void *) waitlist->counterp); diff --git a/rt/aio_suspend.c b/rt/aio_suspend.c index 70c5e1a3ce4..6736857ba15 100644 --- a/rt/aio_suspend.c +++ b/rt/aio_suspend.c @@ -1,5 +1,5 @@ /* Suspend until termination of a requests. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -64,6 +64,7 @@ aio_suspend (list, nent, timeout) 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; } diff --git a/rt/lio_listio.c b/rt/lio_listio.c index 03c3bf2f6b9..13d1b79a585 100644 --- a/rt/lio_listio.c +++ b/rt/lio_listio.c @@ -1,5 +1,5 @@ /* Enqueue and list of read or write requests. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -21,6 +21,7 @@ #include #include #include +#include #include "aio_misc.h" @@ -77,8 +78,17 @@ lio_listio (mode, list, nent, sig) { /* We don't have anything to do except signalling if we work asynchronously. */ + + /* Release the mutex. We do this before raising a signal since the + signal handler might do a `siglongjmp' and then the mutex is + locked forever. */ + pthread_mutex_unlock (&__aio_requests_mutex); + if (mode == LIO_NOWAIT) - __aio_notify_only (sig); + __aio_notify_only (sig, + sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0); + + return result; } else if (mode == LIO_WAIT) { @@ -95,6 +105,7 @@ lio_listio (mode, list, nent, sig) waitlist[cnt].next = requests[cnt]->waiting; waitlist[cnt].counterp = &total; waitlist[cnt].sigevp = NULL; + waitlist[cnt].caller_pid = 0; /* Not needed. */ requests[cnt]->waiting = &waitlist[cnt]; ++total; } @@ -130,6 +141,7 @@ lio_listio (mode, list, nent, sig) } else { + pid_t caller_pid = sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0; total = 0; for (cnt = 0; cnt < nent; ++cnt) @@ -140,6 +152,7 @@ lio_listio (mode, list, nent, sig) waitlist->list[cnt].next = requests[cnt]->waiting; waitlist->list[cnt].counterp = &waitlist->counter; waitlist->list[cnt].sigevp = &waitlist->sigev; + waitlist->list[cnt].caller_pid = caller_pid; requests[cnt]->waiting = &waitlist->list[cnt]; ++total; } diff --git a/rt/lio_listio64.c b/rt/lio_listio64.c index 9cb1125f652..5df2596c0fe 100644 --- a/rt/lio_listio64.c +++ b/rt/lio_listio64.c @@ -1,5 +1,5 @@ /* Enqueue and list of read or write requests, 64bit offset version. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -21,6 +21,7 @@ #include #include #include +#include #include "aio_misc.h" @@ -77,8 +78,17 @@ lio_listio64 (mode, list, nent, sig) { /* We don't have anything to do except signalling if we work asynchronously. */ + + /* Release the mutex. We do this before raising a signal since the + signal handler might do a `siglongjmp' and then the mutex is + locked forever. */ + pthread_mutex_unlock (&__aio_requests_mutex); + if (mode == LIO_NOWAIT) - __aio_notify_only (sig); + __aio_notify_only (sig, + sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0); + + return result; } else if (mode == LIO_WAIT) { @@ -95,6 +105,7 @@ lio_listio64 (mode, list, nent, sig) waitlist[cnt].next = requests[cnt]->waiting; waitlist[cnt].counterp = &total; waitlist[cnt].sigevp = NULL; + waitlist[cnt].caller_pid = 0; /* Not needed. */ requests[cnt]->waiting = &waitlist[cnt]; ++total; } @@ -130,6 +141,7 @@ lio_listio64 (mode, list, nent, sig) } else { + pid_t caller_pid = sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0; total = 0; for (cnt = 0; cnt < nent; ++cnt) @@ -140,6 +152,7 @@ lio_listio64 (mode, list, nent, sig) waitlist->list[cnt].next = requests[cnt]->waiting; waitlist->list[cnt].counterp = &waitlist->counter; waitlist->list[cnt].sigevp = &waitlist->sigev; + waitlist->list[cnt].caller_pid = caller_pid; requests[cnt]->waiting = &waitlist->list[cnt]; ++total; } diff --git a/sysdeps/generic/aio_sigqueue.c b/sysdeps/generic/aio_sigqueue.c index 0a871e24d96..bc703518d41 100644 --- a/sysdeps/generic/aio_sigqueue.c +++ b/sysdeps/generic/aio_sigqueue.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -23,7 +23,7 @@ #include "aio_misc.h" int -__aio_sigqueue (int sig, const union sigval val) +__aio_sigqueue (int sig, const union sigval val, pid_t caller_pid) { __set_errno (ENOSYS); return -1; diff --git a/sysdeps/unix/sysv/linux/aio_sigqueue.c b/sysdeps/unix/sysv/linux/aio_sigqueue.c index 0500b3fbfab..94a8ce0d2a4 100644 --- a/sysdeps/unix/sysv/linux/aio_sigqueue.c +++ b/sysdeps/unix/sysv/linux/aio_sigqueue.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -32,9 +32,10 @@ extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *); /* Return any pending signal or wait for one for the given time. */ int -__aio_sigqueue (sig, val) +__aio_sigqueue (sig, val, caller_pid) int sig; const union sigval val; + pid_t caller_pid; { siginfo_t info; @@ -42,7 +43,7 @@ __aio_sigqueue (sig, val) info.si_signo = sig; info.si_errno = 0; info.si_code = SI_ASYNCIO; - info.si_pid = getpid (); + info.si_pid = caller_pid; info.si_uid = getuid (); info.si_value = val; -- 2.47.3