Index: ClientHTTPBase.pm =================================================================== RCS file: /repository/perlbal/perlbal/lib/Perlbal/ClientHTTPBase.pm,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- ClientHTTPBase.pm 1 May 2007 12:05:44 -0000 1.8 +++ ClientHTTPBase.pm 30 Aug 2007 14:48:18 -0000 1.9 @@ -384,13 +384,22 @@ my $file = $svc->{docroot} . $uri; - # update state, since we're now waiting on stat - $self->state('wait_stat'); + # state update + $self->state('wait_open'); + + Perlbal::AIO::aio_open($file, 0, 0, sub { + my $rp_fh = shift; + # update state, since we're now waiting on stat + $self->state('wait_stat'); - Perlbal::AIO::aio_stat($file, sub { + Perlbal::AIO::aio_stat($rp_fh || $file, sub { # client's gone anyway - return if $self->{closed}; - unless (-e _) { + if ($self->{closed}) { + CORE::close($rp_fh) if $rp_fh; + return; + } + unless (-e _ && ($rp_fh || not -f _)) { + CORE::close($rp_fh) if $rp_fh; return if $self->{service}->run_hook('static_get_poststat_file_missing', $self); return $self->_simple_response(404); } @@ -429,7 +438,10 @@ # partial content $res = $self->{res_headers} = Perlbal::HTTPHeaders->new_response(206); } else { - return if $self->{service}->run_hook('static_get_poststat_pre_send', $self, $mtime); + if ($self->{service}->run_hook('static_get_poststat_pre_send', $self, $mtime)) { + CORE::close($rp_fh) if $rp_fh; + return; + } $res = $self->{res_headers} = Perlbal::HTTPHeaders->new_response(200); } @@ -458,7 +470,10 @@ # has to happen after content-length is set to work: $self->setup_keepalive($res); - return if $self->{service}->run_hook('modify_response_headers', $self); + if ($self->{service}->run_hook('modify_response_headers', $self)) { + CORE::close($rp_fh) if $rp_fh; + return; + } if ($rm eq "HEAD" || $not_mod || $not_satisfiable) { # we can return already, since we know the size @@ -466,28 +481,10 @@ $self->state('xfer_resp'); $self->write($res->to_string_ref); $self->write(sub { $self->http_response_sent; }); + CORE::close($rp_fh) if $rp_fh; return; } - # state update - $self->state('wait_open'); - - Perlbal::AIO::aio_open($file, 0, 0, sub { - my $rp_fh = shift; - - # if client's gone, just close filehandle and abort - if ($self->{closed}) { - CORE::close($rp_fh) if $rp_fh; - return; - } - - # handle errors - if (! $rp_fh) { - # couldn't open the file we had already successfully stat'ed. - # FIXME: do 500 vs. 404 vs whatever based on $! - return $self->close('aio_open_failure'); - } - $self->state('xfer_disk'); $self->tcp_cork(1); # cork writes to self $self->write($res->to_string_ref); @@ -500,12 +497,17 @@ $self->{reproxy_file} = $file; $self->reproxy_fh($rp_fh, $size); - }); } elsif (-d _) { + CORE::close($rp_fh) if $rp_fh; $self->try_index_files($hd, $res, $uri); + } else { + # Not a file or a dir! + CORE::close($rp_fh) if $rp_fh; + return $self->_simple_response(403); # Forbidden! } }); + }); } sub _serve_request_multiple {