--- IO-AIO/AIO.pm 2007/10/03 21:27:51 1.116 +++ IO-AIO/AIO.pm 2007/10/06 14:05:19 1.117 @@ -185,13 +185,15 @@ package IO::AIO; +use Carp (); + no warnings; use strict 'vars'; use base 'Exporter'; BEGIN { - our $VERSION = '2.5'; + our $VERSION = '2.51'; our @AIO_REQ = qw(aio_sendfile aio_read aio_write aio_open aio_close aio_stat aio_lstat aio_unlink aio_rmdir aio_readdir aio_scandir aio_symlink @@ -315,17 +317,65 @@ Asynchronously close a file and call the callback with the result code. -Unlike the other functions operating on files, this function uses the -PerlIO layer to close the filehandle. The reason is that the PerlIO API -insists on closing the underlying fd itself, no matter what, and doesn't -allow modifications to the fd. Unfortunately, it is not clear that you can -call PerlIO from different threads (actually, its quite clear that this -won't work in some cases), so while it likely works perfectly with simple -file handles (such as the ones created by C) it might fail in -interesting ways for others. +Unfortunately, you can't do this to perl. Perl I very strongly on +closing the file descriptor associated with the filehandle itself. Here is +what aio_close will try: + + 1. dup()licate the fd + 2. asynchronously close() the duplicated fd + 3. dup()licate the fd once more + 4. let perl close() the filehandle + 5. asynchronously close the duplicated fd + +The idea is that the first close() flushes stuff to disk that closing an +fd will flush, so when perl closes the fd, nothing much will need to be +flushed. The second async. close() will then flush stuff to disk that +closing the last fd to the file will flush. + +Just FYI, SuSv3 has this to say on close: + + All outstanding record locks owned by the process on the file + associated with the file descriptor shall be removed. + + If fildes refers to a socket, close() shall cause the socket to be + destroyed. ... close() shall block for up to the current linger + interval until all data is transmitted. + [this actually sounds like a specification bug, but who knows] + +And at least Linux additionally actually flushes stuff on every close, +even when the file itself is still open. + +Sounds enourmously inefficient and complicated? Yes... please show me how +to nuke perl's fd out of existence... + +=cut + +sub aio_close($;$) { + aio_block { + my ($fh, $cb) = @_; + + my $pri = aioreq_pri; + my $grp = aio_group $cb; + + my $fd = fileno $fh; + + defined $fd or Carp::croak "aio_close called with fd-less filehandle"; + + # if the dups fail we will simply get EBADF + my $fd2 = _dup $fd; + aioreq_pri $pri; + add $grp _aio_close $fd2, sub { + my $fd2 = _dup $fd; + close $fh; + aioreq_pri $pri; + add $grp _aio_close $fd2, sub { + $grp->result ($_[0]); + }; + }; -Having said that, aio_close tries to clean up the filehandle as much as -possible before handing it to an io thread, and generally does work. + $grp + } +} =item aio_read $fh,$offset,$length, $data,$dataoffset, $callback->($retval)