From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.0 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id C87551FEAA; Sun, 19 Jun 2016 07:12:49 +0000 (UTC) Date: Sun, 19 Jun 2016 07:12:49 +0000 From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 2/1] http: constrain getline/close responses by time Message-ID: <20160619071249.GA17405@dcvr.yhbt.net> References: <20160619063241.27195-1-e@80x24.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160619063241.27195-1-e@80x24.org> List-Id: This allows us to yield control to other clients gracefully if getline takes too long to generate a chunk. This is more expensive but should not cost a syscall on modern 64-bit systems. --- lib/PublicInbox/HTTP.pm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/PublicInbox/HTTP.pm b/lib/PublicInbox/HTTP.pm index e0ed2d1..800b240 100644 --- a/lib/PublicInbox/HTTP.pm +++ b/lib/PublicInbox/HTTP.pm @@ -16,6 +16,7 @@ use Fcntl qw(:seek); use Plack::HTTPParser qw(parse_http_request); # XS or pure Perl use HTTP::Status qw(status_message); use HTTP::Date qw(time2str); +use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC); use Scalar::Util qw(weaken); use IO::File; use constant { @@ -25,6 +26,8 @@ use constant { CHUNK_MAX_HDR => 256, }; +sub now () { clock_gettime(CLOCK_MONOTONIC) } + # FIXME: duplicated code with NNTP.pm, layering violation my $WEAKEN = {}; # string(inbox) -> inbox my $weakt; @@ -267,14 +270,14 @@ sub getline_response { my $forward = $self->{forward}; # limit our own running time for fairness with other # clients and to avoid buffering too much: - my $n = 100; + my $end = now() + 0.1; while ($forward && defined(my $buf = $forward->getline)) { $write->($buf); last if $self->{closed}; if ($self->{write_buf_size}) { $self->write($self->{pull}); return; - } elsif ((--$n) <= 0) { + } elsif (now() > $end) { PublicInbox::EvCleanup::asap($self->{pull}); return; }