- # $ENV{GIT_PROJECT_ROOT} = $git->{git_dir};
- $ENV{GIT_HTTP_EXPORT_ALL} = '1';
- $ENV{PATH_TRANSLATED} = "$git->{git_dir}/$path";
- dup2(fileno($in), 0) or die "redirect stdin failed: $!\n";
- dup2(fileno($out), 1) or die "redirect stdout failed: $!\n";
- my @cmd = qw(git http-backend);
- exec(@cmd) or die 'exec `' . join(' ', @cmd). "' failed: $!\n";
- }
+ $fh->close if $fh; # async-only
+ };
+
+ # Danga::Socket users, we queue up the read_enable callback to
+ # fire after pending writes are complete:
+ my $buf = '';
+ my $rd_hdr = sub {
+ my $r = sysread($rpipe, $buf, 1024, length($buf));
+ return if !defined($r) && ($!{EINTR} || $!{EAGAIN});
+ return r(500, 'http-backend error') unless $r;
+ $r = parse_cgi_headers(\$buf) or return; # incomplete headers
+ $r->[0] == 403 ? serve_dumb($env, $git, $path) : $r;
+ };
+ my $res;
+ my $async = $env->{'pi-httpd.async'}; # XXX unstable API
+ my $cb = sub {
+ my $r = $rd_hdr->() or return;
+ $rd_hdr = undef;
+ if (scalar(@$r) == 3) { # error:
+ if ($async) {
+ $async->close; # calls rpipe->close
+ } else {
+ $rpipe->close;
+ $end->();
+ }
+ $res->($r);
+ } elsif ($async) {
+ $fh = $res->($r);
+ $async->async_pass($env->{'psgix.io'}, $fh, \$buf);
+ } else { # for synchronous PSGI servers
+ require PublicInbox::GetlineBody;
+ $r->[2] = PublicInbox::GetlineBody->new($rpipe, $end,
+ $buf);
+ $res->($r);
+ }
+ };
+ sub {
+ ($res) = @_;