]> Sergey Matveev's repositories - public-inbox.git/commitdiff
http: yield body->getline running time
authorEric Wong <e@80x24.org>
Mon, 30 May 2016 04:39:57 +0000 (04:39 +0000)
committerEric Wong <e@80x24.org>
Mon, 30 May 2016 04:46:23 +0000 (04:46 +0000)
We cannot let a client monopolize the single-threaded server
even if it can drain the socket buffer faster than we can
emit data.

While we're at it, acknowledge the this behavior (which happens
naturally) in httpd/async.

The same idea is present in NNTP for the long_response code.

This is the HTTP followup to:
commit 0d0fde0bff97 ("nntp: introduce long response API for streaming")
commit 79d8bfedcdd2 ("nntp: avoid signals for long responses")

lib/PublicInbox/HTTP.pm
lib/PublicInbox/HTTPD/Async.pm

index fcbd758af2d75dc7baf56fbc63e31b0fdd0a6017..6df1c3fc566aebf1688fd3f1665542297279a684 100644 (file)
@@ -265,10 +265,13 @@ sub getline_response {
        my $pull = $self->{pull} = sub {
                local $/ = \8192;
                my $forward = $self->{forward};
+               # limit our own running time for fairness with other
+               # clients and to avoid buffering too much:
+               my $n = 100;
                while ($forward && defined(my $buf = $forward->getline)) {
                        $write->($buf);
                        last if $self->{closed};
-                       if ($self->{write_buf_size}) {
+                       if ((--$n) <= 0 || $self->{write_buf_size}) {
                                $self->write($self->{pull});
                                return;
                        }
index add07ce481b86e2a755aa0eb52b67628201b30a8..fadf2d3abb9aaf6fe63f7c27cf5e68f567a318ab 100644 (file)
@@ -45,7 +45,9 @@ sub async_pass {
                                $self->watch_read(0);
                                $io->write($restart_read); # D::S::write
                        }
-                       return; # stay in watch_read
+                       # stay in watch_read, but let other clients
+                       # get some work done, too.
+                       return;
                } elsif (!defined $r) {
                        return if $!{EAGAIN} || $!{EINTR};
                }