about summary refs log tree commit homepage
path: root/t/ds-leak.t
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-06-01 21:43:47 +0000
committerEric Wong <e@80x24.org>2019-06-01 21:45:24 +0000
commit1d94048ba6094b9b3bbefe279e066c3992b30408 (patch)
treef344baeca7a8e8d1d0d31aa026f0b93efa84de59 /t/ds-leak.t
parentf4bcc588998c6c4fcf816d7cac16f00ef47bd256 (diff)
downloadpublic-inbox-1d94048ba6094b9b3bbefe279e066c3992b30408.tar.gz
ds: fix and test for FD leaks with kqueue on ->Reset
Even though we currently don't use it repeatedly, ->Reset
should close() kqueue FDs and not cause the process to run
out of descriptors.

Add a close-on-exec test while we're at it.
Diffstat (limited to 't/ds-leak.t')
-rw-r--r--t/ds-leak.t52
1 files changed, 52 insertions, 0 deletions
diff --git a/t/ds-leak.t b/t/ds-leak.t
new file mode 100644
index 00000000..9e3243e9
--- /dev/null
+++ b/t/ds-leak.t
@@ -0,0 +1,52 @@
+# Copyright (C) 2019 all contributors <meta@public-inbox.org>
+# Licensed the same as Danga::Socket (and Perl5)
+# License: GPL-1.0+ or Artistic-1.0-Perl
+#  <https://www.gnu.org/licenses/gpl-1.0.txt>
+#  <https://dev.perl.org/licenses/artistic.html>
+use strict;
+use warnings;
+use Test::More;
+use_ok 'PublicInbox::DS';
+
+subtest('close-on-exec for epoll and kqueue' => sub {
+        use PublicInbox::Spawn qw(spawn);
+        my $pid;
+        my $evfd_re = qr/(?:kqueue|eventpoll)/i;
+
+        PublicInbox::DS->SetLoopTimeout(0);
+        PublicInbox::DS->SetPostLoopCallback(sub { 0 });
+        PublicInbox::DS->AddTimer(0, sub { $pid = spawn([qw(sleep 10)]) });
+        PublicInbox::DS->EventLoop;
+        ok($pid, 'subprocess spawned');
+        my @of = grep(/$evfd_re/, `lsof -p $pid 2>/dev/null`);
+        my $err = $?;
+        SKIP: {
+                skip "lsof missing? (\$?=$err)", 1 if $err;
+                is_deeply(\@of, [], 'no FDs leaked to subprocess');
+        };
+        if (defined $pid) {
+                kill(9, $pid);
+                waitpid($pid, 0);
+        }
+        PublicInbox::DS->Reset;
+});
+
+SKIP: {
+        # not bothering with BSD::Resource
+        chomp(my $n = `/bin/sh -c 'ulimit -n'`);
+
+        # FreeBSD 11.2 with 2GB RAM gives RLIMIT_NOFILE=57987!
+        if ($n > 1024 && !$ENV{TEST_EXPENSIVE}) {
+                skip "RLIMIT_NOFILE=$n too big w/o TEST_EXPENSIVE for $0", 1;
+        }
+        my $cb = sub {};
+        for my $i (0..$n) {
+                PublicInbox::DS->SetLoopTimeout(0);
+                PublicInbox::DS->SetPostLoopCallback($cb);
+                PublicInbox::DS->EventLoop;
+                PublicInbox::DS->Reset;
+        }
+        ok(1, "Reset works and doesn't hit RLIMIT_NOFILE ($n)");
+};
+
+done_testing;