Eric Wong [Wed, 16 Oct 2019 00:39:56 +0000 (00:39 +0000)]
mda: support --no-precheck option
Since -mda now supports List-ID to better support mirroring of
existing mailing lists, it probably makes sense to support
disabling the precheck function to provide more accurate (though
potentially spammier) mirrors of lists
Eric Wong [Wed, 16 Oct 2019 00:30:28 +0000 (00:30 +0000)]
Merge branch 'listid'
* listid:
wwwtext: show listid config directive(s)
mda, watch: wire up List-ID header support
config: allow "0" as a valid mainrepo path
config: avoid unnecessary '||' use
config: simplify lookup* methods
config: we always have {-section_order}
Config.pm: Add support for mailing list information
Eric Wong [Mon, 7 Oct 2019 20:52:31 +0000 (20:52 +0000)]
admin: show failing directory
Since public-inbox-index may be run against a large list of
(intended) inboxes from the command-line, it's helpful to show
which directory fails the resolution.
Eric Wong [Tue, 15 Oct 2019 01:11:58 +0000 (01:11 +0000)]
config: simplify lookup* methods
This ensures we always process inboxes in section order and
reduces the amount of code we have to maintain for each lookup.
Avoiding the cost of inboxes object creation is not worth the
code overhead; and we can implement a config cache via Storable
easily for large configs and -mda users.
Eric Wong [Tue, 15 Oct 2019 00:38:06 +0000 (00:38 +0000)]
config: we always have {-section_order}
Rewrite a bunch of tests to use ordered input (emulating
"git config -l" output) so we can always walk sections in
the order they were given in the config file.
Eric W. Biederman [Fri, 17 May 2019 00:22:46 +0000 (19:22 -0500)]
Config.pm: Add support for mailing list information
The world has turned since I first started following mailing lists and
to my surprise every mailing list that I am subscribed to properly
sets the "List-ID:" mailing list header. So instead of doing
something clever and flexible I am adding support for looking up
public inbox mailing lists by their mailing list name.
That makes the work needed for each email trivial and easy to understand.
- Parse the "List-ID:" header.
- Lookup in the configuration which mailbox is connected to that
"List-ID:"
- Deliver the mail to that mailbox.
To that end this change enhances PublicInbox to have an additional
mailbox configuration parameter "listid" that holds the mailing list
name.
A method is added to the PublicInbox config object called
lookup_list_id that given a mailing list name will return the
PublicInbox in the configuration that is configured to handle that
mailing list.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
[ew: avoid autovivification of $ibx->{listid} for t/config.t]
Eric W. Biederman [Tue, 15 Jan 2019 22:36:42 +0000 (16:36 -0600)]
PublicInbox::Import Smuggle a raw message into add
I don't trust the MIME type to not munge my email messages in horrible
ways upon occasion. Therefore allow for passing in the raw message
value instead of trusting the mime object to preserve it.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
[ew: use "//" from Perl 5.10+ for defined check]
Eric Wong [Tue, 15 Oct 2019 03:59:26 +0000 (03:59 +0000)]
INSTALL: recommend inotify|kqueue modules for -watch
Jan Kiszka reported high polling frequency when using -watch.
It turns out OS-specific packages for Filesys::Notify::Simple do
not pull in interfaces to use kqueue or inotify, which are
required to perform power-efficient event-based wakeups on
Maildir writes.
Fix the name of the Filesys::Notify::Simple for FreeBSD while
we're at it.
Eric Wong [Fri, 13 Sep 2019 08:57:02 +0000 (08:57 +0000)]
t/git-http-backend: disable worker processes
We want to ensure we run lsof(8) on the worker (if needed),
and not the master, which doesn't serve requests.
This was originally on top of a test-only patch in
https://public-inbox.org/meta/20190913015043.17149-1-e@80x24.org/
In any case, no point in spawning extra processes for this test.
Alyssa Ross [Wed, 9 Oct 2019 13:21:14 +0000 (13:21 +0000)]
doc: explain publicinbox.<name>.watchheader
It wasn't clear to me exactly what this does -- in particular, what
happens if it isn't specified? Does it support multiple values? A
very brief explanation can answer both of these questions without
making somebody look at the code.
Eric Wong [Tue, 8 Oct 2019 08:58:06 +0000 (08:58 +0000)]
doc: PublicInbox::SaPlugin::ListMirror manpage
This is a plugin for SpamAssassin that happens to be quite
useful in keeping spam off lists I mirror. Hopefully more
people can find it useful now that it has a manpage.
Eric Wong [Sun, 6 Oct 2019 23:56:51 +0000 (23:56 +0000)]
examples: add grok-pull post_update_hook example
This requires the latest (to be in 1.2) -init changes for
synchronization and has no dependencies on GNU or bash-isms
so it should run on *BSD systems without GNU tools.
It does attempt to use curl on <$INBOX_URL/_/text/config/raw>,
but curl is fairly standard nowadays, and falls back to using
an invalid address to initialize.
Eric Wong [Sun, 6 Oct 2019 23:31:36 +0000 (23:31 +0000)]
doc: generate NEWS, NEWS.atom, and NEWS.html
We'll use our Documentation/RelNotes directory and internal APIs
to generate these files for website use (the website should be
completely reproducible).
Eric Wong [Thu, 3 Oct 2019 07:21:59 +0000 (07:21 +0000)]
init: implement locking
First, we use flock(2) to wait on parallel public-inbox-init(1)
invocations while we make multiple changes using git-config(1).
This flock allows -init processes to wait on each other if using
reasonable POSIX filesystems.
Then, we also need a git-config(1)-compatible lock to prevent
user-invoked git-config(1) processes from clobbering our
changes while we're holding the flock.
Eric Wong [Thu, 3 Oct 2019 07:57:29 +0000 (07:57 +0000)]
t/search: bail out on `git init --shared' failures
We can save future testers some time if we bail out early
on "git init --shared" failures, since things like seccomp
or non-POSIX FSes would trigger failures.
BAIL_OUT has been in Test::Simple since Perl v5.10.0, so it's
old-enough to call for our purposes.
Eric Wong [Tue, 1 Oct 2019 23:18:02 +0000 (23:18 +0000)]
listener: warn on some accept()/accept4() errors
We need to warn when hitting file or socket memory limits
or misconfigurations which clear O_NONBLOCK to make it easier
to diagnose configuration problems. We'll also warn on
some other errors in case bugs creep in...
Eric Wong [Tue, 1 Oct 2019 07:01:30 +0000 (07:01 +0000)]
www: fix absolute URLs when mounted under a subdir
While we avoid generating absolute URLs in most cases, our
"git clone" instructions and URL headers in mboxrd files
contain full URLs.
So do the same thing we do for WwwAtomStream and pre-generate
the full URL before Plack::App::URLMap changes $env->{PATH_INFO}
and $env->{SCRIPT_NAME} back to their original values.
Eric Wong [Tue, 1 Oct 2019 01:03:55 +0000 (01:03 +0000)]
TODO: update with "git cat-file" items
Millions of inboxes in an instance is probably not feasible, but
dozens or even hundreds could happen and
/proc/sys/fs/pipe-user-pages-soft is only 16384 on my system,
with each "cat-file --batch" process using 16+1 pages worth
of pipes.
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.
Eric Wong [Fri, 27 Sep 2019 10:48:25 +0000 (10:48 +0000)]
wwwtext: support $INBOX_URL/_/text/config/raw
This returns a git-config(1)-compatible file to make it easier
to get started on mirroring an existing public-inbox. Omitting
the "raw" from the URL works, as well, but I'm not sure if
it's very useful.
Alyssa Ross [Tue, 24 Sep 2019 20:05:55 +0000 (20:05 +0000)]
hlmod: update for highlight 3.51 API change
Quoting Amitai Schleier, who made this same change in ikiwiki[1],
where lots of the public-inbox highlight code comes from:
> As of 3.51, searchFile() is no longer provided in highlight's Perl
> bindings (at least on NetBSD and OS X, as built from pkgsrc). This
> leaves us falling through to getConfDir(), which has been gone
> rather longer.
>
> From highlight git, it appears searchFile() and getFiletypesConfPath()
> both originated in the 3.14 release. The latter is still available in
> 3.51, and returns the same result searchFile() used to. Switch to it.
So, this should still be compatible with the version of highlight.pm in
Debian, but add support for newer versions as well.
Eric Wong [Thu, 26 Sep 2019 01:50:38 +0000 (01:50 +0000)]
httpd: disable Deflater middleware by default on Perl <5.18
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:
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);
Eric Wong [Thu, 26 Sep 2019 01:50:37 +0000 (01:50 +0000)]
ds: workaround a memory leak in Perl 5.16.x
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.
Eric Wong [Tue, 24 Sep 2019 03:39:03 +0000 (03:39 +0000)]
spawnpp: use absolute path for exec
We support "-env" to clear the environment with spawn(),
which causes test failures but no runtime failures
(since "-env" isn't used anywhere in our real code)
Reported-and-tested-by: Alyssa Ross <hi@alyssa.is>
Eric Wong [Sat, 21 Sep 2019 00:06:42 +0000 (00:06 +0000)]
doc: update HACKING and TODO with a few items
Inline::C seems alright, so we might use it more since it still
allows end users to quickly make changes. Our performance on
rotational disks is also terrible, and could be improved...
Eric Wong [Fri, 20 Sep 2019 02:42:14 +0000 (02:42 +0000)]
wwwatomstream: fix per-feed <id>
We were emitting the same "<id>mailto:name@domain</id>" tag
for every feed (but not per-feed entry). This could cause
feed readers to mistake the top (news.atom) feed for other
feeds (search results, or per-thread feeds).
This is technically a breaking change for people relying on
per-thread or per-query feeds, but the only alternative is
to remain broken for anybody trying to follow multiple feeds
off the same inbox.
Eric Wong [Wed, 18 Sep 2019 19:50:50 +0000 (19:50 +0000)]
config: boolean handling matches git-config(1)
We need to handle arbitrary integers and case-insensitive
variations of human words to match git-config(1) behavior,
since that's what users would expect given we use config
files parseable by git-config(1).
Eric Wong [Sat, 14 Sep 2019 19:50:34 +0000 (19:50 +0000)]
doc: add release notes directory
The v1.2.0 is a work-in-progress, while the others are copied
out of our mail archives.
Eventually, a NEWS file will be generated from these emails and
distributed in the release tarball. There'll also be an Atom
feed for the website reusing our feed generation code.
Eric Wong [Tue, 17 Sep 2019 08:31:23 +0000 (08:31 +0000)]
http: remove unnecessary delete
Only removing $http->{env} is needed to prevent circular
references. $env->{'psgix.io'} does not need to be deleted
since $env will no longer have any references to it when
->close returns.
Eric Wong [Tue, 17 Sep 2019 08:31:20 +0000 (08:31 +0000)]
qspawn: shorten lifetime of circular references
All of these circular references are designed to clear
themselves, but these will make actual errors from Devel::Cycle
easier-to-spot.
The circular reference in the limiter {run_queue} is not a real
problem, but we can avoid storing the circular reference until
we actually need to spawn the child, reducing the size of the
Qspawn object while it's in the queue, slightly.
We also do not need to have redundant checks to spawn new
processes, we should only spawn new processes when they're
->start-ed or after waitpid reaps them.
Eric Wong [Tue, 17 Sep 2019 08:31:18 +0000 (08:31 +0000)]
qspawn: remove return value from ->finish
We don't use the return value in real code since we do waitpid
asynchronously, now. So simplify our runtime code at the cost
of making our test slighly more complex.
Eric Wong [Sun, 15 Sep 2019 02:25:34 +0000 (02:25 +0000)]
qspawn: shorten lifetime of environ and opts args
We don't need to hold onto the subprocess environ and
redirects/options for popen_rd after spawning the child process.
I do not expect this to fix problem of leaking unlinked regular
file descriptors (which I still can't reproduce), and it
definitely does not fix the problem of leaking pipe descriptors
(which I also can't reproduce).
This will save an FD sooner on non-public-inbox-httpd servers
which give a non-FD $env->{'psgi.input'}, however
Regardless, it's good to free up memory resources in our own
process ASAP we're done using them.
Eric Wong [Sun, 15 Sep 2019 01:00:06 +0000 (01:00 +0000)]
qspawn: clarify and improve error handling
EINTR should not happen when using non-blocking sockets like we
do in our daemons, but maybe some OSes allow it to happen and
edge-triggered notifications won't notify us again.
So always retry immediately on EINTR without relying on kqueue
or epoll to notify us, and log any other unrecoverable errors
which may happen while we're at it.
Eric Wong [Sat, 14 Sep 2019 18:28:54 +0000 (18:28 +0000)]
doc: update nntpd with NNTPS and STARTTLS examples
NNTPS and STARTTLS seems to be working for several months
without incident on news.public-inbox.org, so consider it a
success and maybe others can try using it.
HTTPS technically works, too, but isn't documented at
the moment since I can't recommend production deployments
without varnish protecting it.
Eric Wong [Thu, 12 Sep 2019 23:16:52 +0000 (23:16 +0000)]
githttpbackend: use REMOTE_ADDR for deleted identifier
REMOTE_HOST is not set by us (it is the reverse DNS name) of
REMOTE_ADDR, and there's few better ways to kill HTTP server
performance than to use standard name resolution APIs like
getnameinfo(3).
Eric Wong [Thu, 12 Sep 2019 08:34:20 +0000 (08:34 +0000)]
tmpfile: give temporary files meaningful names
Although we always unlink temporary files, give them a
meaningful name so that we can we can still make sense
of the pre-unlink name when using lsof(8) or similar
tools on Linux.
Eric Wong [Sat, 14 Sep 2019 09:21:14 +0000 (09:21 +0000)]
qspawn: simplify by using PerlIO::scalar
I didn't know PerlIO::scalar existed until a few months ago,
but it's been distributed with Perl since 5.8 and doesn't
seem to be split out into it's own package on any distro.
Eric Wong [Thu, 12 Sep 2019 06:54:28 +0000 (06:54 +0000)]
solvergit: don't drop update-index stdin with qspawn
It's possible for Qspawn callers to be deferred, in which case
we must ensure we don't cause the temporary file used for
stdin to become unref-ed and closed.
This can be a problem when we exceed the default Qspawn
limiter of 32 concurrent processes for "git update-index".
Eric Wong [Sun, 8 Sep 2019 10:41:12 +0000 (10:41 +0000)]
nntp: regexp always consumes rbuf if "\n" exists
We don't want to get hung into a state where we see "\n" via
index(), yet cannot consume rbuf in the while loop. So tweak
the regexp to ensure we always consume rbuf.
I suspect this is what causes occasional 100% CPU usage of
-nntpd, but reproducing it's been difficult..
Eric Wong [Sun, 14 Jul 2019 02:56:36 +0000 (02:56 +0000)]
nntpdeflate: reduce overhead of idle clients
We don't need to keep an empty buffer around in the common case
when a client is sending us completely inflatable requests and
we're able to read them in one go.
This only seems to save about 2M with 10K NNTPS clients using
COMPRESS, so it's not a huge win, but better than nothing.
Eric Wong [Sat, 13 Jul 2019 21:38:11 +0000 (21:38 +0000)]
nntp: fix LIST OVERVIEW.FMT ordering and format
RFC3977 8.4.2 mandates the order of non-standard headers
to be after the first seven standard headers/metadata;
so "Xref:" must appear after "Lines:"|":lines".
Additionally, non-required header names must be followed
by ":full".
Cc: Jonathan Corbet <corbet@lwn.net> Reported-by: Urs Janßen
<E1hmKBw-0008Bq-8t@akw>
Eric Wong [Sat, 13 Jul 2019 20:27:57 +0000 (20:27 +0000)]
nntpdeflate: stop relying on SUPER for ->do_read
We won't need further layering after enabling compression. So
be explicit about which sub we're calling when we hit ->do_read
from NNTP and eliminate the need for the comment.
Eric Wong [Wed, 10 Jul 2019 06:13:59 +0000 (06:13 +0000)]
http|nntp: avoid recursion inside ->write
In HTTP.pm, we can use the same technique NNTP.pm uses with
long_response with the $long_cb callback and avoid storing
$pull in the per-client structure at all. We can also reuse
the same logic to push the callback into wbuf from NNTP.
This does NOT introduce a new circular reference, but documents
it more clearly.
Eric Wong [Mon, 8 Jul 2019 07:31:19 +0000 (07:31 +0000)]
http|nntp: "use PublicInbox::DS" instead of ->import
Relying on "use" to import during BEGIN means we get to take
advantage of prototype checking of function args during the rest
of the compilation phase.
* origin/nntp-compress:
nntp: improve error reporting for COMPRESS
nntp: reduce memory overhead of zlib
nntp: support COMPRESS DEFLATE per RFC 8054
nntp: move LINE_MAX constant to the top
nntp: use msg_more as a method
Eric Wong [Mon, 8 Jul 2019 07:01:59 +0000 (07:01 +0000)]
ds: use WNOHANG with waitpid if inside event loop
While we're usually not stuck waiting on waitpid after
seeing a pipe EOF or even triggering SIGPIPE in the process
(e.g. git-http-backend) we're reading from, it MAY happen
and we should be careful to never hang the daemon process
on waitpid calls.
v2: use "eq" for string comparison against 'DEFAULT'
Eric Wong [Sun, 7 Jul 2019 06:57:43 +0000 (06:57 +0000)]
nntp: improve error reporting for COMPRESS
Add some checks for errors at initialization, though there's not
much that can be done with ENOMEM-type errors aside from
dropping clients.
We can also get rid of the scary FIXME for MemLevel=8. It was a
stupid error on my part in the original per-client deflate
stream implementation calling C::R::Z::{Inflate,Deflate} in
array context and getting the extra dualvar error code as a
string result, causing the {zin}/{zout} array refs to have
extra array elements.
Eric Wong [Fri, 5 Jul 2019 22:53:39 +0000 (22:53 +0000)]
nntp: reduce memory overhead of zlib
Using Z_FULL_FLUSH at the right places in our event loop, it
appears we can share a single zlib deflate context across ALL
clients in a process.
The zlib deflate context is the biggest factor in per-client
memory use, so being able to share that across many clients
results in a large memory savings.
With 10K idle-but-did-something NNTP clients connected to a
single process on a 64-bit system, TLS+DEFLATE used around
1.8 GB of RSS before this change. It now uses around 300 MB.
TLS via IO::Socket::SSL alone uses <200MB in the same situation,
so the actual memory reduction is over 10x.
This makes compression less efficient and bandwidth increases
around 45% in informal testing, but it's far better than no
compression at all. It's likely around the same level of
compression gzip gives on the HTTP side.
Security implications with TLS? I don't know, but I don't
really care, either... public-inbox-nntpd doesn't support
authentication and it's up to the client to enable compression.
It's not too different than Varnish caching gzipped responses
on the HTTP side and having responses go to multiple HTTPS
clients.