From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 75B981F47E for ; Fri, 6 Jan 2023 10:11:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1672999861; bh=H/tHwNDNcM5LT1eP9tLIqhuMCNHyxgJKW9GPuL22Mz4=; h=From:To:Subject:Date:In-Reply-To:References:From; b=BRp8nQyNDyhWkcPb1HfllSle7w0uM9FEkDQF5DQLtg77cT4oz8h7kDQfDGNx50q8u PizBw5qH6/WycfPZXrFIQX7D+haO6gi1Vt99q+3Nk+tiWlB3zEBzL4VV47fHdB5laP RPenSNieYwLpAnOXS7KxkxKzpztXC4E/0OrrhQMo= From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 2/4] httpd/async: retry reads properly when parsing headers Date: Fri, 6 Jan 2023 10:10:51 +0000 Message-Id: <20230106101053.1461700-3-e@80x24.org> In-Reply-To: <20230106101053.1461700-1-e@80x24.org> References: <20230106101053.1461700-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: While git-http-backend sends headers with one write syscall, upstream cgit still trickles them out line-by-line and we need to account for that and retry Qspawn {parse_hdr} callbacks. --- lib/PublicInbox/HTTPD/Async.pm | 8 +++++--- lib/PublicInbox/Qspawn.pm | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/PublicInbox/HTTPD/Async.pm b/lib/PublicInbox/HTTPD/Async.pm index e03daafa..7bbab1e1 100644 --- a/lib/PublicInbox/HTTPD/Async.pm +++ b/lib/PublicInbox/HTTPD/Async.pm @@ -14,7 +14,7 @@ # arg: arg for {cb} # end_obj: CODE or object which responds to ->event_step when ->close is called package PublicInbox::HTTPD::Async; -use strict; +use v5.12; use parent qw(PublicInbox::DS); use Errno qw(EAGAIN); use PublicInbox::Syscall qw(EPOLLIN); @@ -44,9 +44,9 @@ sub new { sub event_step { my ($self) = @_; - if (my $cb = delete $self->{cb}) { + if (defined $self->{cb}) { # this may call async_pass when headers are done - $cb->(my $refcnt_guard = delete $self->{arg}); + $self->{cb}->($self->{arg}); } elsif (my $sock = $self->{sock}) { # $http may be undef if discarding body output from cgit on 404 my $http = $self->{http} or return $self->close; @@ -76,6 +76,7 @@ sub event_step { # may be PublicInbox::GzipFilter or $PublicInbox::Qspawn::qx_fh sub async_pass { my ($self, $http, $ofh, $bref) = @_; + delete @$self{qw(cb arg)}; # In case the client HTTP connection ($http) dies, it # will automatically close this ($self) object. $http->{forward} = $self; @@ -94,6 +95,7 @@ sub async_pass { sub close { my $self = $_[0]; $self->SUPER::close; # DS::close + delete @$self{qw(cb arg)}; # we defer this to the next timer loop since close is deferred if (my $end_obj = delete $self->{end_obj}) { diff --git a/lib/PublicInbox/Qspawn.pm b/lib/PublicInbox/Qspawn.pm index f8cbffcb..7984e35a 100644 --- a/lib/PublicInbox/Qspawn.pm +++ b/lib/PublicInbox/Qspawn.pm @@ -134,7 +134,7 @@ sub start ($$$) { } } -sub psgi_qx_init_cb { +sub psgi_qx_init_cb { # this may be PublicInbox::HTTPD::Async {cb} my ($self) = @_; my $async = delete $self->{async}; # PublicInbox::HTTPD::Async my ($r, $buf); @@ -223,7 +223,7 @@ sub rd_hdr ($) { $ret; } -sub psgi_return_init_cb { +sub psgi_return_init_cb { # this may be PublicInbox::HTTPD::Async {cb} my ($self) = @_; my $r = rd_hdr($self) or return; my $env = $self->{psgi_env};