user/dev discussion of public-inbox itself
 help / color / Atom feed
* [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7
@ 2019-09-26  1:50 Eric Wong
  2019-09-26  1:50 ` [PATCH 1/2] ds: workaround a memory leak in Perl 5.16.x Eric Wong
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Eric Wong @ 2019-09-26  1:50 UTC (permalink / raw)
  To: meta

After many hours of reviewing our code in PublicInbox::Qspawn,
PublicInbox::GitHTTPBackend, and PublicInbox::HTTP and finding
nothing but cleanups and documentation improvements; it seems
the leaks affecting lore is down to bugs in Perl 5.16.3.

After removing the warning for Deflater being missing in
d883d4a93b23be134038e28f421eafca70c3d838
("httpd: get rid of Deflater warning"), I missed that my
own CentOS 7 VM was missing that module so was unable to
reproduce the FD leaks :x

The first patch is a straightforward workaround that I was
able to test without Plack::Middleware::Deflater being installed.

The second patch stops loading Deflater in httpd on Perls
earlier than 5.18.  (But I haven't built or tested 5.18 myself).
Enabling gzip in varnish will be needed for 5.16 users.

Independently of this fix, I've long been considering replacing
Deflater with a buffer-to-gzip layer which would reduce memory
pressure from intermediate uncompressed strings.  This might
serve as impetus to move that idea along (and of course I'd
test it heavily under CentOS 7 :>).

Anybody using custom .psgi files on Perl 5.16.x will need to
make adjustments to disable the Deflater in that.

Eric Wong (2):
  ds: workaround a memory leak in Perl 5.16.x
  httpd: disable Deflater middleware by default on Perl <5.18

 lib/PublicInbox/DS.pm     | 9 ++++++---
 script/public-inbox-httpd | 8 +++++++-
 2 files changed, 13 insertions(+), 4 deletions(-)

-- 
EW


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] ds: workaround a memory leak in Perl 5.16.x
  2019-09-26  1:50 [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7 Eric Wong
@ 2019-09-26  1:50 ` Eric Wong
  2019-09-26  1:50 ` [PATCH 2/2] httpd: disable Deflater middleware by default on Perl <5.18 Eric Wong
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2019-09-26  1:50 UTC (permalink / raw)
  To: meta

The perl-5.16.3-294.el7_6 RPM package on RHEL/CentOS 7 is
affected by a memory leak in Perl when calling `ref' on
blessed references.  This resulted in a very slow leak that
manifests more quickly with a nonstop "git fetch" loop.

Use Scalar::Util::blessed to work around the issue.
Tested overnight on a CentOS 7 VM.

cf. https://rt.perl.org/Public/Bug/Display.html?id=114340
---
 lib/PublicInbox/DS.pm | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/lib/PublicInbox/DS.pm b/lib/PublicInbox/DS.pm
index 30a9641..7f7cb85 100644
--- a/lib/PublicInbox/DS.pm
+++ b/lib/PublicInbox/DS.pm
@@ -24,6 +24,7 @@ use parent qw(Exporter);
 our @EXPORT_OK = qw(now msg_more);
 use warnings;
 use 5.010_001;
+use Scalar::Util qw(blessed);
 
 use PublicInbox::Syscall qw(:epoll);
 use PublicInbox::Tmpfile;
@@ -178,10 +179,12 @@ sub next_tick () {
     my $q = $nextq;
     $nextq = [];
     for (@$q) {
-        if (ref($_) eq 'CODE') {
-            $_->();
-        } else {
+        # we avoid "ref" on blessed refs to workaround a Perl 5.16.3 leak:
+        # https://rt.perl.org/Public/Bug/Display.html?id=114340
+        if (blessed($_)) {
             $_->event_step;
+        } else {
+            $_->();
         }
     }
 }
-- 
EW


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/2] httpd: disable Deflater middleware by default on Perl <5.18
  2019-09-26  1:50 [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7 Eric Wong
  2019-09-26  1:50 ` [PATCH 1/2] ds: workaround a memory leak in Perl 5.16.x Eric Wong
@ 2019-09-26  1:50 ` Eric Wong
  2019-09-26 12:36 ` [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7 Konstantin Ryabitsev
  2019-09-27 21:01 ` [PATCH 3/2] qspawn: workaround Perl 5.16.3 leak, re-enable Deflater Eric Wong
  3 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2019-09-26  1:50 UTC (permalink / raw)
  To: meta

Testing with perl-5.16.3-294.el7_6 RPM package on RHEL/CentOS 7,
the Deflater middleware triggers a leak when used in conjunction
with our push-based responses from PublicInbox::Qspawn.

I could not find another solution to workaround the memory leak
in this case, and I could not find a specific leak fix in
the perl5180delta manpage[1] which looked like it would
solve our problem.

Attempting to workaround the issue proved futile.  Using
internal Deflater-specific keys to prevent deflating in
GitHTTPBackend and Qspawn did not solve the problem:

        $env->{"plack.skip-deflater"} = 1;
        $env->{"psgix.no-compress"} = 1;

Nor did forcing an invalid encoding via "git fetch":

	git -c http.extraheader=Accept-Encoding:gzap fetch

So this appears to be a problem with Plack::Util::response_cb
somewhere.

This does NOT appear to be a problem with ref() leaking as in
DS::next_tick[2], since I couldn't find where
Plack::Middleware::Deflater or Plack::Util::response_cb would be
calling ref() on a blessed reference to trigger a leak.

Also, oddly enough, the ref() use for backwards compatibility at
the top of PublicInbox::GitHTTPBackend::serve does NOT seem to
trigger a leak on 5.16.3 due to [2]:

	# XXX compatibility... ugh, can we stop supporting this?
	$git = PublicInbox::Git->new($git) unless ref($git);

[1] https://perldoc.perl.org/perl5180delta.html
[2] https://rt.perl.org/Public/Bug/Display.html?id=114340
---
 script/public-inbox-httpd | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/script/public-inbox-httpd b/script/public-inbox-httpd
index b2464f4..9b869f9 100755
--- a/script/public-inbox-httpd
+++ b/script/public-inbox-httpd
@@ -24,7 +24,13 @@ my $refresh = sub {
 		my $www = PublicInbox::WWW->new;
 		$www->preload;
 		$app = builder {
-			eval {
+			# Perl 5.16.3 leaks in our "push" response code path
+			# (e.g. Qspawn) due to something in
+			# Plack::Util::response_cb, regardless of whether the
+			# client is sending Accept-Encoding:gzip requests.
+			# perl5180delta documents many leak fixes, so assume
+			# 5.18+ is safe for now and bump the check as-need:
+			$] >= 5.018000 and eval {
 				enable 'Deflater',
 					content_type => [ qw(
 						text/html
-- 
EW


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7
  2019-09-26  1:50 [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7 Eric Wong
  2019-09-26  1:50 ` [PATCH 1/2] ds: workaround a memory leak in Perl 5.16.x Eric Wong
  2019-09-26  1:50 ` [PATCH 2/2] httpd: disable Deflater middleware by default on Perl <5.18 Eric Wong
@ 2019-09-26 12:36 ` Konstantin Ryabitsev
  2019-09-26 21:16   ` Eric Wong
  2019-09-27 21:01 ` [PATCH 3/2] qspawn: workaround Perl 5.16.3 leak, re-enable Deflater Eric Wong
  3 siblings, 1 reply; 6+ messages in thread
From: Konstantin Ryabitsev @ 2019-09-26 12:36 UTC (permalink / raw)
  To: Eric Wong; +Cc: meta

On Thu, Sep 26, 2019 at 01:50:36AM +0000, Eric Wong wrote:
>After many hours of reviewing our code in PublicInbox::Qspawn,
>PublicInbox::GitHTTPBackend, and PublicInbox::HTTP and finding
>nothing but cleanups and documentation improvements; it seems
>the leaks affecting lore is down to bugs in Perl 5.16.3.
>
>After removing the warning for Deflater being missing in
>d883d4a93b23be134038e28f421eafca70c3d838
>("httpd: get rid of Deflater warning"), I missed that my
>own CentOS 7 VM was missing that module so was unable to
>reproduce the FD leaks :x
>
>The first patch is a straightforward workaround that I was
>able to test without Plack::Middleware::Deflater being installed.
>
>The second patch stops loading Deflater in httpd on Perls
>earlier than 5.18.  (But I haven't built or tested 5.18 myself).
>Enabling gzip in varnish will be needed for 5.16 users.

Yay, I can confirm that the latest master fixes all the FD leaks that 
have been plaguing lore.kernel.org for the past few weeks. The number of 
pipes is stable and there are no (deleted) tempfiles showing up. Thanks 
so much for this!

Can you elaborate on gzip+varnish changes? I'm assuming it's something 
as simple as:

@@ -63,6 +63,10 @@
        } else {
                /* short TTL for up-to-dateness, our PSGI is not that slow */
                set beresp.ttl = 10s;
+               /* Compress text responses on CentOS7 */
+               if (beresp.http.content-type ~ "text") {
+                       set beresp.do_gzip = true;
+               }
        }
        return (deliver);
 }

-K

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7
  2019-09-26 12:36 ` [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7 Konstantin Ryabitsev
@ 2019-09-26 21:16   ` Eric Wong
  0 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2019-09-26 21:16 UTC (permalink / raw)
  To: Konstantin Ryabitsev; +Cc: meta

Konstantin Ryabitsev <konstantin@linuxfoundation.org> wrote:
> On Thu, Sep 26, 2019 at 01:50:36AM +0000, Eric Wong wrote:
> > After many hours of reviewing our code in PublicInbox::Qspawn,
> > PublicInbox::GitHTTPBackend, and PublicInbox::HTTP and finding
> > nothing but cleanups and documentation improvements; it seems
> > the leaks affecting lore is down to bugs in Perl 5.16.3.
> > 
> > After removing the warning for Deflater being missing in
> > d883d4a93b23be134038e28f421eafca70c3d838
> > ("httpd: get rid of Deflater warning"), I missed that my
> > own CentOS 7 VM was missing that module so was unable to
> > reproduce the FD leaks :x
> > 
> > The first patch is a straightforward workaround that I was
> > able to test without Plack::Middleware::Deflater being installed.
> > 
> > The second patch stops loading Deflater in httpd on Perls
> > earlier than 5.18.  (But I haven't built or tested 5.18 myself).
> > Enabling gzip in varnish will be needed for 5.16 users.
> 
> Yay, I can confirm that the latest master fixes all the FD leaks that have
> been plaguing lore.kernel.org for the past few weeks. The number of pipes is
> stable and there are no (deleted) tempfiles showing up. Thanks so much for
> this!

Good to know!  Also, how's memory use?

It ought to be stable if Perl is doing the right thing; but I
haven't tested all the endpoints thoroughly on 5.16.3
(especially the mbox.gz ones)

> Can you elaborate on gzip+varnish changes? I'm assuming it's something as
> simple as:
> 
> @@ -63,6 +63,10 @@
>        } else {
>                /* short TTL for up-to-dateness, our PSGI is not that slow */
>                set beresp.ttl = 10s;
> +               /* Compress text responses on CentOS7 */
> +               if (beresp.http.content-type ~ "text") {
> +                       set beresp.do_gzip = true;
> +               }

*shrug*  Whatever the varnish docs says :)

I still prefer to do gzip in the Perl process to minimize IPC
overhead (and to eventually make things easier-to-deploy w/o
needing Varnish).

I think I can add gzip support to WwwStream and WwwAtomStream
pretty easily, and we're already using a custom gzipper for
the mboxrd endpoints.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/2] qspawn: workaround Perl 5.16.3 leak, re-enable Deflater
  2019-09-26  1:50 [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7 Eric Wong
                   ` (2 preceding siblings ...)
  2019-09-26 12:36 ` [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7 Konstantin Ryabitsev
@ 2019-09-27 21:01 ` Eric Wong
  3 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2019-09-27 21:01 UTC (permalink / raw)
  To: meta

The httpd-supplied write callback is the leak culprit under Perl
5.16.3.  undef-ing it immediately after use keeps a repeated
"git fetch" loop from monotonically increasing memory and FD use
on the Perl shipped with RHEL/CentOS 7.x.

Other endpoints tested showed no increase in memory use under
constant load with "ab -HAccept-Encoding:gzip -k", including the
async psgi_qx code path used by $INBOX_URL/$OBJECT_ID/s/ via
SolverGit module.
---
 Note: I initially tried this change, but thought it only slowed
 down the leaking because I had not yet discovered the
 workaround in commit cd71a869c7e9c811
 ("ds: workaround a memory leak in Perl 5.16.x").

 Now that both leaks are worked around, memory usage is completely
 flat when repeating a single request of any type with gzip-enabled.

 lib/PublicInbox/Qspawn.pm | 4 ++++
 script/public-inbox-httpd | 8 +-------
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/lib/PublicInbox/Qspawn.pm b/lib/PublicInbox/Qspawn.pm
index 5a30064..cb3dc51 100644
--- a/lib/PublicInbox/Qspawn.pm
+++ b/lib/PublicInbox/Qspawn.pm
@@ -281,6 +281,10 @@ sub psgi_return {
 								$buf, $filter);
 			$wcb->($r);
 		}
+
+		# Workaround a leak under Perl 5.16.3 when combined with
+		# Plack::Middleware::Deflater:
+		$wcb = undef;
 	};
 	$limiter ||= $def_limiter ||= PublicInbox::Qspawn::Limiter->new(32);
 	my $start_cb = sub { # may run later, much later...
diff --git a/script/public-inbox-httpd b/script/public-inbox-httpd
index 9b869f9..b2464f4 100755
--- a/script/public-inbox-httpd
+++ b/script/public-inbox-httpd
@@ -24,13 +24,7 @@ my $refresh = sub {
 		my $www = PublicInbox::WWW->new;
 		$www->preload;
 		$app = builder {
-			# Perl 5.16.3 leaks in our "push" response code path
-			# (e.g. Qspawn) due to something in
-			# Plack::Util::response_cb, regardless of whether the
-			# client is sending Accept-Encoding:gzip requests.
-			# perl5180delta documents many leak fixes, so assume
-			# 5.18+ is safe for now and bump the check as-need:
-			$] >= 5.018000 and eval {
+			eval {
 				enable 'Deflater',
 					content_type => [ qw(
 						text/html
-- 
EW


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, back to index

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-26  1:50 [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7 Eric Wong
2019-09-26  1:50 ` [PATCH 1/2] ds: workaround a memory leak in Perl 5.16.x Eric Wong
2019-09-26  1:50 ` [PATCH 2/2] httpd: disable Deflater middleware by default on Perl <5.18 Eric Wong
2019-09-26 12:36 ` [PATCH 0/2] leak workarounds for Perl 5.16 on CentOS/RHEL 7 Konstantin Ryabitsev
2019-09-26 21:16   ` Eric Wong
2019-09-27 21:01 ` [PATCH 3/2] qspawn: workaround Perl 5.16.3 leak, re-enable Deflater Eric Wong

user/dev discussion of public-inbox itself

Archives are clonable:
	git clone --mirror https://public-inbox.org/meta
	git clone --mirror http://czquwvybam4bgbro.onion/meta
	git clone --mirror http://hjrcffqmbrq6wope.onion/meta
	git clone --mirror http://ou63pmih66umazou.onion/meta

Example config snippet for mirrors

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.mail.public-inbox.meta
	nntp://ou63pmih66umazou.onion/inbox.comp.mail.public-inbox.meta
	nntp://czquwvybam4bgbro.onion/inbox.comp.mail.public-inbox.meta
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.mail.public-inbox.meta
	nntp://news.gmane.org/gmane.mail.public-inbox.general

 note: .onion URLs require Tor: https://www.torproject.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox