Bug 5508 - close does not work on sockets with pending aio
: close does not work on sockets with pending aio
Status: RESOLVED INVALID
Product: glibc
Classification: Unclassified
Component: libc
: unspecified
: P2 normal
: ---
Assigned To: Ulrich Drepper
:
:
:
:
  Show dependency treegraph
 
Reported: 2007-12-18 10:26 UTC by Pierre Habouzit
Modified: 2008-04-07 18:23 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pierre Habouzit 2007-12-18 10:26:52 UTC
The following code demonstrates what I believe is the same issue as
was originally reported, but does so reading from stdin.  Once the
aio_read has begun and blocked, aio_cancel is unable to interrupt
it until some data does arrive to be read.

This means it is not possible to destroy the input buffer for a
read that you no longer care to get (or know you will never get)
since if some data does later arrive, the aio_handler function
will still be called.  If none ever does, you'll accrue a 'zombie'
thread for the remaining life of the process.  Neither of which
is a great situation...  so I do hope we can fix this.

Cheers,
Ron


$ gcc aio.c -o aio -lrt
$ ./aio
aww poo.


/* aio.c */
#include <stdio.h>
#include <unistd.h>
#include <aio.h>

static void aio_handler(union sigval data)
{
    printf("aio read\n");
}

int main()
{
    struct aiocb aio;
    char         buf;

    aio.aio_fildes  = STDIN_FILENO;
    aio.aio_offset  = 0;
    aio.aio_buf     = &buf;
    aio.aio_nbytes  = 1;
    aio.aio_reqprio = 0;
    aio.aio_sigevent.sigev_notify            = SIGEV_THREAD;
    aio.aio_sigevent.sigev_notify_function   = aio_handler;
    aio.aio_sigevent.sigev_notify_attributes = NULL;
    aio.aio_sigevent.sigev_value.sival_ptr   = NULL;

    aio_read( &aio );

    sleep(1);

    if( aio_cancel( STDIN_FILENO, &aio ) == AIO_NOTCANCELED )
        printf("aww poo.\n");
    else
        printf("woo hoo!\n");

    return 0;
}
Comment 1 Carlos Eduardo Seo 2008-04-02 20:42:47 UTC
I confirmed that the test-case is well formed and reproducing against glibc-cvs.

By checking aio_error() after the sleep() call, we can see that aio_read() is
still EINPROGRESS. And aio_cancel() is indeed returning AIO_NOTCANCELLED.

I tried writing EOF to stdin before the aio_cancel() call but it still returns
AIO_NOTCANCELLED. I also tried LF and the result is the same. So aio_cancel()
can't interrupt aio_read() even after data arrives in stdin.

Is an aio_read() on stdin valid?  If so is there a way to terminate the
aio_read() when it is no longer needed?  Should there be a way to force an
aio_cancel() on something that will traditionally never finish?

Regards,

Carlos
Comment 2 Jakub Jelinek 2008-04-02 20:55:32 UTC
http://www.opengroup.org/onlinepubs/009695399/functions/aio_cancel.html

"Which operations are cancelable is implementation-defined."
and
"The value AIO_NOTCANCELED shall be returned if at least one of the requested
operation(s) cannot be canceled because it is in progress."

That's the case here for the pure userland aio implementation, if an operation
is already in progress as in this case, it is not cancellable.
Comment 3 Ulrich Drepper 2008-04-07 18:23:56 UTC
aio is designed for file I/O.  Not everything works as you might like it for
other types of devices.  We're not complicating the implementation dramatically
to handle these cases especially since the standard explicitly does not require
it.  If you want a better implementation, get sufficient support in the kernel.