[patch] aio_write
Amos Waterland
apw@us.ibm.com
Fri Jun 14 08:22:00 GMT 2002
> > 4) If on completion of the __aio_enqueue_request errno==EINTR set
> > errno to 0 as this is in fact not an error and a residual of the
> > fact that the TEMP_FAILURE_RETRY macro does not reset errno when
> > pwrite is interrupted. (Can this macro be changed? Should it?)
>
> This looks broken. errno is only defiend when the function fails and
> since it does not fail in this case why are you changing it?
Andreas:
Hi, I just wanted to jump in and explain what Tom meant. Here is a
small test case that shows the behavior of concern for the pread(2)
case (see below for code listing for test0025.c):
% ./test0025
./test0025: did not fail (ret: 0), but errno: 4
n a m e s e r v
I believe that any syscall invocation wrapped in the TEMP_FAILURE_RETRY
macro will exhibit the same behavior: i.e. errno sometimes being left to
EINTR (#defined as 4), because the syscall was interrupted one more more
times before successful completion.
In aio_misc.c::handle_fildes_io(), the following code handles write
requests (lines 523-547):
else if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_WRITE)
{
if (aiocbp->aiocb.aio_lio_opcode & 128)
aiocbp->aiocb.__return_value =
TEMP_FAILURE_RETRY (__pwrite64 (fildes, (const void *)
aiocbp->aiocb64.aio_buf,
aiocbp->aiocb64.aio_nbytes,
aiocbp->aiocb64.aio_offset));
else
aiocbp->aiocb.__return_value =
TEMP_FAILURE_RETRY (pwrite (fildes, (const void *)
aiocbp->aiocb.aio_buf,
aiocbp->aiocb.aio_nbytes,
aiocbp->aiocb.aio_offset));
}
In unistd.h::TEMP_FAILURE_RETRY, the code loops while the wrapped
syscall is interrupted:
# define TEMP_FAILURE_RETRY(expression) \
(__extension__ \
({ long int __result; \
do __result = (long int) (expression); \
while (__result == -1L && errno == EINTR); \
__result; }))
The problem, I believe, is that errno is not reset to 0 when the syscall
actually makes it through without being interrupted. I hope this makes
sense, thanks.
Amos Waterland
---- Begin test0025.c ----
/* Show that TEMP_FAILURE_RETRY does not reset errno if it is EINTR.
* Amos Waterland <apw@us.ibm.com>
* 14 June 2002
*/
#include <aio.h>
#include <error.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main( int argc, char *argv[] )
{
const int BYTES = 8;
int i, r, fd;
char buff[BYTES];
struct aiocb cb;
if ((fd = open( "/etc/resolv.conf", O_RDONLY )) < 0)
error( 1, errno, "opening file" );
cb.aio_fildes = fd;
cb.aio_offset = 0;
cb.aio_buf = buff;
cb.aio_nbytes = BYTES;
cb.aio_reqprio = 0;
cb.aio_sigevent.sigev_notify = SIGEV_NONE;
errno = 0;
if ((r = aio_read( &cb )))
error( 1, errno, "reading from file" );
if (r == 0 && errno != 0)
error( 0, 0, "did not fail (ret: %i), but errno: %i", r, errno );
while (aio_error( &cb ) == EINPROGRESS) { usleep( 10 ); }
for (i = 0; i < BYTES; i++) { printf( "%c ", buff[i] ); } printf( "\n" );
return 0;
}
---- End test0025.c ----
More information about the Libc-alpha
mailing list