]> Sergey Matveev's repositories - public-inbox.git/log
public-inbox.git
3 years agolei: default "-f $mfolder" args for common MUAs
Eric Wong [Sat, 23 Jan 2021 10:27:50 +0000 (10:27 +0000)]
lei: default "-f $mfolder" args for common MUAs

At least mail, mailx, mutt, and neomutt follow this convention.
Heirloom mailx doesn't support Maildir (our default), but GNU
mailutils mail/mailx does.

3 years agolei: oneshot: preserve stdout if writing mbox
Eric Wong [Sat, 23 Jan 2021 10:27:49 +0000 (10:27 +0000)]
lei: oneshot: preserve stdout if writing mbox

We still need stdout if launching an MUA.

3 years agolei_to_mail: drop cyclic reference if not using IPC
Eric Wong [Sat, 23 Jan 2021 10:27:48 +0000 (10:27 +0000)]
lei_to_mail: drop cyclic reference if not using IPC

This may fix another interrupt-related segfault I'm occasionally
seeing (but so far unable to reproduce).

3 years agolei: support remote externals
Eric Wong [Sat, 23 Jan 2021 10:27:47 +0000 (10:27 +0000)]
lei: support remote externals

Via curl(1), since that lets us easily use tor on a
per-connection basis via LD_PRELOAD (torsocks) or proxy.
We'll eventually support more curl options which can allow
users to get past firewalls and deal with other odd network
configurations.

3 years agolei: move external vivification to xsearch
Eric Wong [Sat, 23 Jan 2021 10:27:46 +0000 (10:27 +0000)]
lei: move external vivification to xsearch

This seems like a better place to put it given upcoming
URI support, which starts in this commit.

3 years agolei forget-external: bash completion support
Eric Wong [Thu, 21 Jan 2021 19:46:24 +0000 (19:46 +0000)]
lei forget-external: bash completion support

The tricky bit was getting around word splitting bash
does on URLs.  This may work with other shells, too.

3 years agolei: forget-external support with canonicalization
Eric Wong [Thu, 21 Jan 2021 19:46:23 +0000 (19:46 +0000)]
lei: forget-external support with canonicalization

For proper matching, we'll do a better job canonicalizing
URLs and path names for matching.  Of course, users may edit
the file outside of lei, so ensure we try both the canonicalized
and as-is form provided by the user.

I also don't think we'll need to store externals info in
MiscIdx; just the config file is fine.

3 years agolei: remove @TO_CLOSE_ATFORK_CHILD
Eric Wong [Thu, 21 Jan 2021 19:46:22 +0000 (19:46 +0000)]
lei: remove @TO_CLOSE_ATFORK_CHILD

..At least limit it to a single file handle.  The write end
EOFpipe can be limited in scope and auto-closed when $quit is
clobbered, leaving only the listener.  The listener is the only
handle that needs to be closed explicitly due to it being on the
stack in the Listener->event_step => accept_dispatch => lei_$FOO
code path.

Everything else gets clobbered by DS->Reset in children after
forking.

3 years agolei_xsearch: reduce reference paths to lxs
Eric Wong [Thu, 21 Jan 2021 19:46:21 +0000 (19:46 +0000)]
lei_xsearch: reduce reference paths to lxs

Having an extra reference to LeiXSearch from the OpPipe $done_op
map is unnecessary and makes the reference graph more complex
than it needs to be.  Just use $lei->{lxs} to simplify and
reduce the likelyhood of bugs.

3 years agolei: remove INT/QUIT/TERM handlers, fix daemon EOF
Eric Wong [Thu, 21 Jan 2021 19:46:20 +0000 (19:46 +0000)]
lei: remove INT/QUIT/TERM handlers, fix daemon EOF

The signal handlers on the client side were unnecessary,
all we need is to handle socket EOF properly in the daemon
by killing xsearch and l2m workers.

3 years agolei: oneshot: use client $io[2] for placeholder
Eric Wong [Thu, 21 Jan 2021 19:46:19 +0000 (19:46 +0000)]
lei: oneshot: use client $io[2] for placeholder

STDERR may actually get closed in ->ipc_atfork_child in
oneshot mode, so ensure we pass in a valid file handle
to avoid warnings ->wq_do.

3 years agolei_to_mail: avoid segfault on exit
Eric Wong [Thu, 21 Jan 2021 19:46:18 +0000 (19:46 +0000)]
lei_to_mail: avoid segfault on exit

Worker exit causes DESTROY ordering to become unpredictable and
leads to Perl segfaulting.  Instead, rely on OnDestroy and
explicit triggering after wq_worker_loop to ensure we finish
all outstanding git requests before worker exit.

3 years agolei: fix inadvertant FD sharing
Eric Wong [Thu, 21 Jan 2021 19:46:17 +0000 (19:46 +0000)]
lei: fix inadvertant FD sharing

$wq->{-ipc_atfork_child_close} neededed to be initialized properly.
And start setting $0 in workers to improve visibility.

3 years agolei: show {pct} and {oid} in From_ lines and filenames
Eric Wong [Thu, 21 Jan 2021 19:46:16 +0000 (19:46 +0000)]
lei: show {pct} and {oid} in From_ lines and filenames

From_ lines are shown when mbox* variants are output to stdout,
making {oid} and {pct} information visible without risking being
propagated to other importer processes if they were in
lei-specific X-* headers.

Maildirs already had OIDs in the filename, now they gain Xapian
{pct} in case anybody cares.

3 years agolei_xsearch: eliminate some unused, commented-out code
Eric Wong [Thu, 21 Jan 2021 19:46:15 +0000 (19:46 +0000)]
lei_xsearch: eliminate some unused, commented-out code

3 years agolei q: retrieve keywords for local, non-external messages
Eric Wong [Thu, 21 Jan 2021 19:46:14 +0000 (19:46 +0000)]
lei q: retrieve keywords for local, non-external messages

This isn't tested for now, so maybe it works.

3 years agolei_overview: rename {relevance} => {pct}
Eric Wong [Thu, 21 Jan 2021 19:46:13 +0000 (19:46 +0000)]
lei_overview: rename {relevance} => {pct}

The old name was too long compared to the rest of the field
names.  With the Xapian method being named ->get_percent,
"pct" is a well known abbreviation for "percent" and already
used internally by our wrapper.

..And cleanup some excess whitespace while we're in the area.

3 years agolei_to_mail: call PublicInbox::IPC::DESTROY
Eric Wong [Wed, 20 Jan 2021 05:04:49 +0000 (14:04 +0900)]
lei_to_mail: call PublicInbox::IPC::DESTROY

It doesn't seem to matter at the moment, but it should
save us from some surprises down the line.

3 years agolei_xsearch: keep l2m->{-wq_s1} while preparing query
Eric Wong [Wed, 20 Jan 2021 05:04:48 +0000 (14:04 +0900)]
lei_xsearch: keep l2m->{-wq_s1} while preparing query

This caused a performance regression which made parallel
lei2mail processes fail prematurely and fall back to
writing blobs in the lei_xsearch worker.

3 years agolei: dump and clear errors.log in daemon mode
Eric Wong [Wed, 20 Jan 2021 05:04:47 +0000 (14:04 +0900)]
lei: dump and clear errors.log in daemon mode

Inspired by "dmesg -c", this should help users report bugs
and avoids eating up $XDG_RUNTIME_DIR.

Once lei is ready for release, hopefully the need for this
should be few an far between, but shit happens.

3 years agolei q: cleanup store initialization
Eric Wong [Wed, 20 Jan 2021 05:04:46 +0000 (14:04 +0900)]
lei q: cleanup store initialization

Since we no longer leak an FD for over.sqlite3, we can
initialize and actually enable it by default as originally
intended.

3 years agooveridx: eidx_prep: fix leftover dbh reference
Eric Wong [Wed, 20 Jan 2021 05:04:45 +0000 (14:04 +0900)]
overidx: eidx_prep: fix leftover dbh reference

Leaving $dbh in another field was causing over.sqlite3 to
remain open after ->dbh_close.  Fix up some minor style
issues while we're at it.

3 years agolei: exit code in oneshot mode
Eric Wong [Wed, 20 Jan 2021 05:04:44 +0000 (14:04 +0900)]
lei: exit code in oneshot mode

waitpid() in DESTROY ends up setting $? for the exit status,
thus we must reap IPC children before calling CORE::exit.

This fixes t/lei-oneshot.t with TEST_RUN_MODE=0

3 years agolei: allow more mbox inode types
Eric Wong [Wed, 20 Jan 2021 05:04:43 +0000 (14:04 +0900)]
lei: allow more mbox inode types

We may attempt to write an mbox to any terminal, block, or
character device, not just regular files and FIFOs/pipes.
The only thing that is known to not work is a directory.

Sockets may be possible with some OSes (e.g. Plan 9) or
filesystems.  This fixes t/lei.t on FreeBSD 11.x

3 years agolei_overview: start implementing format detection
Eric Wong [Tue, 19 Jan 2021 09:34:35 +0000 (09:34 +0000)]
lei_overview: start implementing format detection

We'll need it for IMAP support, at least.  Proper mbox family
detection will be expensive, so deal with it later.

3 years agolei: test some likely errors due to misuse
Eric Wong [Tue, 19 Jan 2021 09:34:34 +0000 (09:34 +0000)]
lei: test some likely errors due to misuse

Because user errors happen...

3 years agot/lei: fix double-running of socket test with oneshot
Eric Wong [Tue, 19 Jan 2021 09:34:33 +0000 (09:34 +0000)]
t/lei: fix double-running of socket test with oneshot

We split out t/lei-oneshot.t and t/lei.t so it's easier
to isolate run-mode specific bugs and behavior and there's
no reason to rerun the socket daemon tests.

3 years agolei_overview: do not write if $lei->{1} is gone
Eric Wong [Tue, 19 Jan 2021 09:34:32 +0000 (09:34 +0000)]
lei_overview: do not write if $lei->{1} is gone

We'll invalidate the {1} (stdout) field on SIGPIPE,
so don't trigger a Perl warning by writing to it.

3 years agolei q: fix augment of compressed mailboxes
Eric Wong [Tue, 19 Jan 2021 09:34:31 +0000 (09:34 +0000)]
lei q: fix augment of compressed mailboxes

We need to delay writing out the mailbox until the compressor
process is up and running, so have startq wait a bit.  This
means we must create the pipe early and hand it off to the
workers before augmenting, despite spawning the
gzip/pigz/xz/bzip2 process after augment is complete.

3 years agolei: write daemon errors to the sock directory
Eric Wong [Tue, 19 Jan 2021 09:34:30 +0000 (09:34 +0000)]
lei: write daemon errors to the sock directory

Most everything should be captured by the __WARN__ handlers and
routed to syslog, but it appears Perl may write to stderr in
some emergency cases, as can libc or other libraries.  Just
point it to a small file that's cleared on reboot.

3 years agolei q: do not spawn MUA early
Eric Wong [Tue, 19 Jan 2021 09:34:29 +0000 (09:34 +0000)]
lei q: do not spawn MUA early

I'm not sure why, but mutt sometimes won't detect small
quickly.  We'll display a progress bar meter when writing
results, instead.

3 years agolei q: fix SIGPIPE handling from lei2mail workers
Eric Wong [Tue, 19 Jan 2021 09:34:28 +0000 (09:34 +0000)]
lei q: fix SIGPIPE handling from lei2mail workers

We need to properly propagate SIGPIPE to the top-level
lei-daemon process and avoid relying on auto-close,
since auto-close triggers Perl warnings when explicit
close() does not.

3 years agolei q: start ->mset while query_prepare runs
Eric Wong [Tue, 19 Jan 2021 09:34:27 +0000 (09:34 +0000)]
lei q: start ->mset while query_prepare runs

We don't need the result of query_prepare (for augmenting or
mass unlinking) until we're ready to deduplicate and write
results to the filesystem.  This ought to let us hide some of
the cost of Xapian searches on multi-device/core systems for
extremely expensive searches.

3 years agolei_to_mail: optimize for MUAs
Eric Wong [Mon, 18 Jan 2021 10:30:32 +0000 (04:30 -0600)]
lei_to_mail: optimize for MUAs

Instead of optimizing our own performance, this optimizes
our data to reduce work done by the MUA consumer.

Maildir and mbox destinations no longer support any notion of
the IMAP \Recent flag.  JMAP has no functioning \Recent
equivalent, and neither do we.

In practice, having MUAs (e.g. mutt) clear the \Recent flag when
committing changes to the mbox is expensive: it creates a
rename(2) storm with Maildir and overwrites the entire mbox.

For mboxcl2 (and mboxcl), we'll further optimize mutt behavior
by setting the Lines: header in addition to Content-Length.

With these changes, mutt exits instantaneously on mboxcl2,
mboxcl, and Maildirs generated by "lei q".

3 years agolei q: parallelize Maildir and mbox writing
Eric Wong [Mon, 18 Jan 2021 10:30:31 +0000 (04:30 -0600)]
lei q: parallelize Maildir and mbox writing

With 4 dedicated workers, this seems to provide a 100-120%
speedup on a 4 core machine when writing thousands of search
results to a Maildir or mbox.  This also sets us up for
high-latency IMAP destinations in the future.

This opens the door to more speedup opportunities such
as optimizing dedupe locking and other ways to reduce
contention.

This change is fairly complex and convoluted, unfortunately.
Further work may allow us to simplify it and even improve
performance.

3 years agolei q: add --mua-cmd switch
Eric Wong [Sun, 17 Jan 2021 08:52:27 +0000 (20:52 -1200)]
lei q: add --mua-cmd switch

It can be convenient to invoke an MUA as search results
are being written to it, as an eager person may want to
start seeing results ASAP.  This lets Maildir users
see results in the MUA as we are writing them.  Users
of IMAP will eventually be able to take advantage of
them, too.

Since we don't support mbox locking (yet?), we'll only invoke
the MUA after results are done for mbox formats.

3 years agolei: pager: pass correct env in oneshot mode
Eric Wong [Sat, 16 Jan 2021 11:36:24 +0000 (23:36 -1200)]
lei: pager: pass correct env in oneshot mode

We want new environment variables when spawning the
pager from oneshot (non-daemon) mode.

3 years agolei: q: results output to Maildir and mbox* working
Eric Wong [Sat, 16 Jan 2021 11:36:23 +0000 (23:36 -1200)]
lei: q: results output to Maildir and mbox* working

All the augment and deduplication stuff seems to be working
based on unit tests.  OpPipe is a nice general addition that
will probably make future state machines easier.

3 years agoipc: children don't kill on DESTROY, reduce FD sharing
Eric Wong [Sat, 16 Jan 2021 11:36:22 +0000 (23:36 -1200)]
ipc: children don't kill on DESTROY, reduce FD sharing

Children should not be blindly killing siblings on ->DESTROY
since they're typically shorter-lived than parents.  We'll
also be more careful about on-stack variables and now we
can rely exclusively on delete ops to close FDs.

We also need to fix our SIGPIPE handling for the oneshot case
while fixing a typo for delete, so we write "!" to the EOF pipe
to ensure the parent oneshot process exits on the first worker
that hits SIGPIPE, rather than waiting for the last worker to
hit SIGPIPE.

3 years agolei_to_mail: prepare for worker offload
Eric Wong [Sat, 16 Jan 2021 11:36:21 +0000 (23:36 -1200)]
lei_to_mail: prepare for worker offload

We'll be doing most of the work in forked off worker processes,
so ensure some of it is fork and serialization-friendly.

3 years agoextindex: fix w/ Xapian 1.2.21..1.2.24
Eric Wong [Sun, 17 Jan 2021 07:09:59 +0000 (07:09 +0000)]
extindex: fix w/ Xapian 1.2.21..1.2.24

Xapian v1.2.21..v1.2.24 failed to set the close-on-exec flag
on the flintlock FD, causing "git cat-file" processes to
hold onto the lock and prevent subsequent Xapian::WritableDatabase
from locking the DB.  So cleanup git processes after committing
the miscidx transaction.

3 years agot/shared_kv: workaround old File::Spec
Eric Wong [Sun, 17 Jan 2021 07:09:58 +0000 (07:09 +0000)]
t/shared_kv: workaround old File::Spec

The version of File::Spec shipped with Perl 5.16.3 memoizes the
value of File::Spec->tmpdir, causing changes to $ENV{TMPDIR}
after-the-fact to be ignored.

We'll only work around this in the test since it's innocuous and
unlikely to matter in real-world usage (and there's many places
where we'd have to workaround this in non-test code).

3 years agot/thread-index-gap: support older DBI
Eric Wong [Sun, 17 Jan 2021 07:09:57 +0000 (07:09 +0000)]
t/thread-index-gap: support older DBI

...by avoiding selectall_array in favor of selectall_arrayref.
Tested with DBI 1.627.

3 years agoinitialize scalar for `vec' perlop modification
Eric Wong [Sun, 17 Jan 2021 07:09:56 +0000 (07:09 +0000)]
initialize scalar for `vec' perlop modification

Older Perls (tested 5.16.3) would warn on uninitialized scalars while
newer (tested 5.28.1) do not.  Just initialize it to an empty string
since it'll be filled in by `vec'.

3 years agoaddress: pairs: enable pure Perl version
Eric Wong [Sun, 17 Jan 2021 07:09:55 +0000 (07:09 +0000)]
address: pairs: enable pure Perl version

Oops, this is needed for systems lacking Email::Address::XS

3 years agolei: pass FD to CWD via cmsg, use fchdir on server
Eric Wong [Thu, 14 Jan 2021 07:06:27 +0000 (19:06 -1200)]
lei: pass FD to CWD via cmsg, use fchdir on server

Perl chdir() automatically does fchdir(2) if given a file
or directory handle since 5.8.8/5.10.0, so we can safely
rely on it given our 5.10.1+ requirement.

This means we no longer have to waste several milliseconds
loading the Cwd.so and making stat() calls to ensure
ENV{PWD} is correct and usable in the server.  It also lets
us work in directories that are no longer accessible via
pathname.

3 years agolei: remove temporary var on open
Eric Wong [Thu, 14 Jan 2021 07:06:26 +0000 (19:06 -1200)]
lei: remove temporary var on open

We can place the IO/GLOB ref directly into $self, here.

3 years agoleixsearch: remove some commented out code
Eric Wong [Thu, 14 Jan 2021 07:06:25 +0000 (19:06 -1200)]
leixsearch: remove some commented out code

Dedupe is active, now, and we have $each_smsg->(...)

3 years agolei: q: lock stdout on overview output
Eric Wong [Thu, 14 Jan 2021 07:06:24 +0000 (19:06 -1200)]
lei: q: lock stdout on overview output

Most writes to stdout aren't atomic and we need locking to
prevent workers from interleaving and corrupting JSON output.
The one case stdout won't require locking is if it's pointed
to a regular file with O_APPEND; as POSIX O_APPEND semantics
guarantees atomicity.

3 years agolei_overview: rename "references" to "refs"
Eric Wong [Thu, 14 Jan 2021 07:06:23 +0000 (19:06 -1200)]
lei_overview: rename "references" to "refs"

"references" was too long of a name compared to the other field
names we output in the JSON.  While we currently don't have a
"refs:" search prefix for the "References:" header, we may in
the future.

3 years agosearch: rename "ts:" prefix to "rt:"
Eric Wong [Thu, 14 Jan 2021 07:06:22 +0000 (19:06 -1200)]
search: rename "ts:" prefix to "rt:"

Meaning "Received time", as it is the best description of the
value we use from the "Received:" header, if present.  JMAP
calls it "receivedAt", but "rt:" seems like a better
abbreviation being in line with "dt:" for the "Date" header.

"Timestamp" ("ts") was potentially ambiguous given the presence
of the "Date" header.

3 years agolei q: reinstate smsg dedupe
Eric Wong [Thu, 14 Jan 2021 07:06:21 +0000 (19:06 -1200)]
lei q: reinstate smsg dedupe

Now that dedupe is serialization and fork-safe, we can
wire it back up in our query results paths.

3 years agolei_dedupe+shared_kv: ensure round-tripping serialization
Eric Wong [Thu, 14 Jan 2021 07:06:20 +0000 (19:06 -1200)]
lei_dedupe+shared_kv: ensure round-tripping serialization

We'll be passing these objects via PublicInbox::IPC which uses
Storable (or Sereal), so ensure they're safe to use after
serialization.

3 years agolei: rely on localized $current_lei for warnings
Eric Wong [Thu, 14 Jan 2021 07:06:19 +0000 (19:06 -1200)]
lei: rely on localized $current_lei for warnings

This lets us get rid of the Sys::Syslog import and __WARN__
override in LeiXSearch, though we still need it with
->atfork_child_wq.

3 years agolei: reduce live FD references in wq child
Eric Wong [Thu, 14 Jan 2021 07:06:18 +0000 (19:06 -1200)]
lei: reduce live FD references in wq child

We can shrink the @TO_CLOSE_ATFORK_CHILD array by two
elements, at least.  I may be possible to eliminate this
array entirely but clobbering $quit doesn't seem to
remove references to $eof_w or the $listener socket.

3 years agolei: do not unlink socket path at exit
Eric Wong [Thu, 14 Jan 2021 07:06:17 +0000 (19:06 -1200)]
lei: do not unlink socket path at exit

This matches existing -httpd/-nntpd/-imapd daemon behavior.
From what I can recall, it is less racy for the process doing
bind(2) to unlink it if stale.

3 years agodaemon+watch: fix localization of %SIG for non-signalfd users
Eric Wong [Thu, 14 Jan 2021 07:06:16 +0000 (19:06 -1200)]
daemon+watch: fix localization of %SIG for non-signalfd users

It turns out "local" did not take effect in the way we used it:
  http://nntp.perl.org/group/perl.perl5.porters/258784
  <CAHhgV8hPbcmkzWizp6Vijw921M5BOXixj4+zTh3nRS9vRBYk8w@mail.gmail.com>

Fortunately, none of the old use cases seem affected, unlike the
previous lei change to ensure consistent SIGPIPE handling.

3 years agolei: test SIGPIPE, stop xsearch workers on client abort
Eric Wong [Thu, 14 Jan 2021 07:06:15 +0000 (19:06 -1200)]
lei: test SIGPIPE, stop xsearch workers on client abort

The new test ensures consistency between oneshot and
client/daemon users.  Cancelling an in-progress result now also
stops xsearch workers to avoid wasted CPU and I/O.

Note the lei->atfork_child_wq usage changes, it is to workaround
a bug in Perl 5: http://nntp.perl.org/group/perl.perl5.porters/258784
<CAHhgV8hPbcmkzWizp6Vijw921M5BOXixj4+zTh3nRS9vRBYk8w@mail.gmail.com>

This switches the internal protocol to use SOCK_SEQPACKET
AF_UNIX sockets to prevent merging messages from the daemon to
client to run pager and kill/exit the client script.

3 years agocmd_ipc: support + test EINTR + EAGAIN, no FDs
Eric Wong [Thu, 14 Jan 2021 07:06:14 +0000 (19:06 -1200)]
cmd_ipc: support + test EINTR + EAGAIN, no FDs

We'll ensure our {send,recv}_cmd4 implementations are
consistent w.r.t. non-blocking and interrupted sockets.

We'll also support receiving messages without FDs associated
so we don't have to send dummy FDs to keep receivers from
reporting EOF.

3 years agolei: query: restore JSON output overview
Eric Wong [Sun, 10 Jan 2021 12:15:19 +0000 (12:15 +0000)]
lei: query: restore JSON output overview

This internal API is better suited for fork-friendliness (but
locking + dedupe still needs to be re-added).

Normal "json" is the default, though stream-friendly "concatjson"
and "jsonl" (AKA "ndjson" AKA "ldjson") all seem working
(though tests aren't working, yet).

For normal "json", the biggest downside is the necessity of a
trailing "null" element at the end of the array because of
parallel processes, since (AFAIK) regular JSON doesn't allow
trailing commas, unlike JavaScript.

3 years agolei_xsearch: transfer 4 FDs internally, drop IO::FDPass
Eric Wong [Sun, 10 Jan 2021 12:15:18 +0000 (12:15 +0000)]
lei_xsearch: transfer 4 FDs internally, drop IO::FDPass

It's easier to make the code more generic by transferring
all four FDs (std(in|out|err) + socket) instead of omitting
stdin.

We'll be reading from stdin on some imports, and possibly
outputting to stdout, so omitting stdin now would needlessly
complicate things.

The differences with IO::FDPass "1" code paths and the "4"
code paths used by Inline::C and Socket::MsgHdr are far too
much to support and test at the moment.

3 years agolei: run pager in client script
Eric Wong [Sun, 10 Jan 2021 12:15:17 +0000 (12:15 +0000)]
lei: run pager in client script

While most single keystrokes work fine when the pager is
launched from the background daemon, Ctrl-C and WINCH can cause
strangeness when connected to the wrong terminal.

3 years agolei: fork + FD cleanup
Eric Wong [Sun, 10 Jan 2021 12:15:16 +0000 (12:15 +0000)]
lei: fork + FD cleanup

Do a better job of closing FDs that we don't want shared with
the work queue workers.  We'll also fix naming and use
"atfork_prepare" instead of "atfork_parent" to match
pthread_atfork(3) naming.

3 years agolei: get rid of client {pid} field
Eric Wong [Sun, 10 Jan 2021 12:15:15 +0000 (12:15 +0000)]
lei: get rid of client {pid} field

Using kill(2) is too dangerous since extremely long
queries may mean the original PID of the aborted lei(1)
client process to be recycled by a new process.  It would
be bad if the lei_xsearch worker process issued a kill
on the wrong process.

So just rely on sending the exit message via socket.

3 years agoipc: drop unused fields, default sighandlers for wq
Eric Wong [Sun, 10 Jan 2021 12:15:14 +0000 (12:15 +0000)]
ipc: drop unused fields, default sighandlers for wq

Relying on signal handlers to kill a particular worker was a
laggy/racy idea and I gave up on the idea of targetting workers
explicitly and instead chose to make wq_worker_decr stop the
next idle worker ->wq_exit.

We will however attempt to support sending signals to
a process group.

3 years agoipc: fix IO::FDPass use with a worker limit of 1
Eric Wong [Sun, 10 Jan 2021 12:15:13 +0000 (12:15 +0000)]
ipc: fix IO::FDPass use with a worker limit of 1

IO::FDPass is our last choice for implementing the workqueue
because its lack of atomicity makes it impossible to guarantee
all requests of a single group hit a single worker out of many.

So the only way to use IO::FDPass for workqueues it to only have
a single worker.  A single worker still buys us a small amount
of parallelism because of the parent process.

3 years agoipc: start supporting sending/receiving more than 3 FDs
Eric Wong [Sun, 10 Jan 2021 12:15:12 +0000 (12:15 +0000)]
ipc: start supporting sending/receiving more than 3 FDs

Actually, sending 4 FDs will be useful for lei internal xsearch
work once we start accepting input from stdin.  It won't be used
with the lightweight lei(1) client, however.

For WWW (eventually), a single FD may be enough.

3 years agolei: query: ensure pager exit is instantaneous
Eric Wong [Sun, 10 Jan 2021 12:15:11 +0000 (12:15 +0000)]
lei: query: ensure pager exit is instantaneous

Improve interactivity and user experience by allowing the user
to return to the terminal immediately when the pager is exited
(e.g. hitting the `q' key in less(1)).

This is a massive change which restructures query handling to
allow parallel search when --thread expansion is in use and
offloading to a separate worker when --thread is not in use.

The Xapian query offload changes allow us to reenter the event
loop right away once the search(es) are shipped off to the work
queue workers.

This means the main lei-daemon process can forget the lei(1)
client socket immediately once it's handed off to worker
processes.

We now unblock SIGPIPE in query workers and send an exit(141)
response to the lei(1) client socket to denote SIGPIPE.

This also allows parallelization for users using "lei q" from
multiple terminals.

JSON output is currently broken and will need to be restructured
for more flexibility and fork-safety.

3 years agolei: fix oneshot TTY detection by passing STD*{GLOB}
Eric Wong [Sun, 10 Jan 2021 12:15:10 +0000 (12:15 +0000)]
lei: fix oneshot TTY detection by passing STD*{GLOB}

...  instead of STD*{IO}.  I'm not sure why *STDOUT{IO} being an
IO::File object disqualifies it from the "-t" perlop check
returning true on TTY, but it does.  So use *STDOUT{GLOB} for
now.

http://nntp.perl.org/group/perl.perl5.porters/258760
Message-ID: <X/kgIqIuh4ZtUZNR@dcvr>

3 years agolei: rename $w to $wpager for warning message
Eric Wong [Sun, 10 Jan 2021 12:15:09 +0000 (12:15 +0000)]
lei: rename $w to $wpager for warning message

Perl keeps track of the variable name for error messages
when auto-closing an FD fails, so this will help identify
the source of a close error..

3 years agoipc: DESTROY and wq_workers methods
Eric Wong [Sun, 10 Jan 2021 12:15:08 +0000 (12:15 +0000)]
ipc: DESTROY and wq_workers methods

We'll enable automatic cleanup when IPC classes go out-of-scope
to avoid leaving zombies around.

->wq_workers will be a useful convenience method to change
worker counts.

3 years agoipc: drop -ipc_parent_pid field
Eric Wong [Sun, 10 Jan 2021 12:15:07 +0000 (12:15 +0000)]
ipc: drop -ipc_parent_pid field

It is not used anywhere.

3 years agoipc: wq: support dynamic worker count change
Eric Wong [Sun, 10 Jan 2021 12:15:06 +0000 (12:15 +0000)]
ipc: wq: support dynamic worker count change

Increasing/decreasing workers count will be useful in
some situations.

3 years agoipc: eliminate ipc_worker_stop method
Eric Wong [Sun, 10 Jan 2021 12:15:05 +0000 (12:15 +0000)]
ipc: eliminate ipc_worker_stop method

We can just EOF the pipe, and instead rely on per-class
error handling to deal with uncommitted transactions and
what not.

3 years agoipc: work queue support via SOCK_SEQPACKET
Eric Wong [Sun, 10 Jan 2021 12:15:04 +0000 (12:15 +0000)]
ipc: work queue support via SOCK_SEQPACKET

This will allow any number of younger sibling processes to
communicate with older siblings directly without relying on a
mediator process.  This is intended to be useful for
distributing search work across multiple workers without caring
which worker hits it (we only care about shard members).

And any request sent with this will be able to hit any worker
without locking on our part.

Unix stream sockets with a listener were also considered;
binding to a file on the FS may confuse users given there's
already a socket path for lei(1).  Linux-only Abstract or
autobind sockets are rejected due to lack of portability.

SOCK_SEQPACKET via socketpair(2) was chosen since it's POSIX
2008 and available on FreeBSD 9+ in addition to Linux, and
doesn't require filesystem access.

3 years agoipc: avoid excessive evals
Eric Wong [Sun, 10 Jan 2021 12:15:03 +0000 (12:15 +0000)]
ipc: avoid excessive evals

We should not need an eval for warning with our code base.
Nowadays, dwaitpid() automatically does the right thing
regardless of whether we're in the event loop, so no eval
is needed there, either.

3 years agocmd_ipc: send FDs with buffer payload
Eric Wong [Sun, 10 Jan 2021 12:15:02 +0000 (12:15 +0000)]
cmd_ipc: send FDs with buffer payload

For another step in in syscall reduction, we'll support
transferring 3 FDs and a buffer with a single sendmsg/recvmsg
syscall using Socket::MsgHdr if available.

Beyond script/lei itself, this will be used for internal IPC
between search backends (perhaps with SOCK_SEQPACKET).  There's
a chance this could make it to the public-facing daemons, too.

This adds an optional dependency on the Socket::MsgHdr package,
available as libsocket-msghdr-perl on Debian-based distros
(but not CentOS 7.x and FreeBSD 11.x, at least).

Our Inline::C version in PublicInbox::Spawn remains the last
choice for script/lei due to the high startup time, and
IO::FDPass remains supported for non-Debian distros.

Since the socket name prefix changes from 3 to 4, we'll also
take this opportunity to make the argv+env buffer transfer less
error-prone by relying on argc instead of designated delimiters.

3 years agoipc: add support for asynchronous callbacks
Eric Wong [Sun, 10 Jan 2021 12:15:01 +0000 (12:15 +0000)]
ipc: add support for asynchronous callbacks

Similar to git->cat_async, this will let us deal with responses
asynchronously, as well as being able to mix synchronous and
asynchronous code transparently (though perhaps not optimally).

3 years agods: block signals when reaping
Eric Wong [Sun, 10 Jan 2021 12:15:00 +0000 (12:15 +0000)]
ds: block signals when reaping

This lets us call dwaitpid long before a process exits
and not have to wait around for it.

This is advantageous for lei where we can run dwaitpid on the
pager as soon as we spawn it, instead of waiting for a client
socket to go away on DESTROY.

3 years agolei q: deduplicate smsg
Eric Wong [Sun, 10 Jan 2021 12:14:59 +0000 (12:14 +0000)]
lei q: deduplicate smsg

We don't want duplicate messages in results overviews, either.

3 years agolei query + pagination sorta working
Eric Wong [Sun, 10 Jan 2021 12:14:58 +0000 (12:14 +0000)]
lei query + pagination sorta working

Parallelism and interactivity with pager + SIGPIPE needs work;
but results are shown and phrase search works without shell
users having to apply Xapian quoting rules on top of standard
shell quoting.

3 years agov2writable: exact discontiguous history handling
Eric Wong [Tue, 5 Jan 2021 01:29:10 +0000 (01:29 +0000)]
v2writable: exact discontiguous history handling

We've always temporarily unindexeded messages before reindexing
them again if there's discontiguous history.

This change improves the mechanism we use to prevent NNTP and
IMAP clients from seeing duplicate messages.

Previously, we relied on mapping Message-IDs to NNTP article
numbers to ensure clients would not see the same message twice.
This worked for most messages, but not for for messages with
reused or duplicate Message-IDs.

Instead of relying on Message-IDs as a key, we now rely on the
git blob object ID for exact content matching.  This allows
truly different messages to show up for NNTP|IMAP clients, while
still those clients from seeing the message again.

3 years agoaddress: pairs: new helper for JMAP (and maybe lei)
Eric Wong [Tue, 5 Jan 2021 09:04:37 +0000 (09:04 +0000)]
address: pairs: new helper for JMAP (and maybe lei)

Per JMAP RFC 8621 sec 4.1.2.3, we should be able to
denote the lack of a phrase/comment corresponding to an
email address with a JSON "null" (or Perl `undef').

  [
    { "name": "James Smythe", "email": "james@example.com" },
    { "name": null, "email": "jane@example.com" },
    { "name": "John Smith", "email": "john@example.com" }
  ]

The new "pairs" method just returns a 2 dimensional array
and the consumer will fill in the field names if necessary
(or not).

lei(1) may use the two dimensional array as-is for JSON output.

3 years agolei: use client env as-is, drop daemon-env command
Eric Wong [Tue, 5 Jan 2021 09:04:36 +0000 (09:04 +0000)]
lei: use client env as-is, drop daemon-env command

There may be subtle misbehaviours when mixing the existing
daemon env and the client-supplied env.  Just do the simplest
thing and use the client env as-is.

We'll also start the ->event_step callback since we'll need
to remember some things for long-lived commands.

3 years agolei: automatic pager support
Eric Wong [Tue, 5 Jan 2021 09:04:35 +0000 (09:04 +0000)]
lei: automatic pager support

Just like git, we'll start a pager when outputting to a terminal
for user-friendliness when reading many messages.

3 years agolei: completion: fix filename completion
Eric Wong [Tue, 5 Jan 2021 09:04:34 +0000 (09:04 +0000)]
lei: completion: fix filename completion

"-o default" is what we want from "complete", "-o filename" just
tells readline the result from the "_lei" function might be a
filename and quote appropriately.

3 years agoimap: fix uninitialized var on MSN search miss
Eric Wong [Tue, 5 Jan 2021 18:19:48 +0000 (18:19 +0000)]
imap: fix uninitialized var on MSN search miss

It seems only triggered by bots trying to steal information.

3 years agolei: improve idempotent "init" error message
Eric Wong [Mon, 4 Jan 2021 04:16:24 +0000 (04:16 +0000)]
lei: improve idempotent "init" error message

Showing "leistore.dir= already initialized" because $cur is
undefined isn't useful.

3 years agolei: fix opt_dash to pass non-dash args to @argv
Eric Wong [Mon, 4 Jan 2021 04:16:23 +0000 (04:16 +0000)]
lei: fix opt_dash to pass non-dash args to @argv

The special "<>" handling in Getopt::Long actually invokes the
callback for every single command-line arg, not just those
prefixed by "-".  This will let us pass arbitrary non-dashed
words for search queries so users can type queries naturally
without quoting (unless they want phrase search).

3 years agolei: prefer IO::FDPass over our Inline::C recv_3fds
Eric Wong [Sun, 3 Jan 2021 20:58:29 +0000 (20:58 +0000)]
lei: prefer IO::FDPass over our Inline::C recv_3fds

While our recv_3fds() implementation is more efficient
syscall-wise, loading Inline takes nearly 50ms on my machine
even after Inline::C memoizes the build.  The current ~20ms in
the fast path is barely acceptable to me, and 50ms would be
unusable.

Eventually, script/lei may invoke tcc(1) or cc(1) directly in
the fast path, but it needs @INC for the slow path, at least.

We'll encode the number of FDs into the socket name allow
parallel installations, for now.

3 years agosearchidxshard: use add_xapian directly for v2
Eric Wong [Sun, 3 Jan 2021 02:06:17 +0000 (02:06 +0000)]
searchidxshard: use add_xapian directly for v2

We can more clearly distinguish between v1 and v2-only code
paths this way, and may be able to save a few cycles this way.

3 years agoipc: switch to one-way pipes
Eric Wong [Sun, 3 Jan 2021 02:06:16 +0000 (02:06 +0000)]
ipc: switch to one-way pipes

This fixes a performance regression in multi-process v2 indexing
due to the switch to PublicInbox::IPC.  While Unix sockets are
fewer FDs to manage, pipes allow unprivileged processes to use
larger buffers (up to 1M) on out-of-the-box Linux instances.

A larger buffer via F_SETPIPE_SZ afforded by pipes was proven
valuable during v2 development in 2018 and continues to be
valuable when we get significant amounts of one-way traffic from
the producer parent to worker children.

Compression may be an option for systems without F_SETPIPE_SZ;
but it increases CPU usage with no memory bandwidth savings on
hosts where larger buffers are available.

3 years agouse Eml (or MIME) objects for all indexing paths
Eric Wong [Sun, 3 Jan 2021 02:06:15 +0000 (02:06 +0000)]
use Eml (or MIME) objects for all indexing paths

We don't need to be keeping the raw message around after it hits
git.  Shard work now relies on Storable (or Sereal) and all of
the indexing code relies on the Email::MIME-like API of Eml to
access interesting parts of the message.

Similarly, smsg->{raw_bytes} is no longer carried around and we
do the CRLF adjustment when setting smsg->{bytes}.

There's also a small simplification to t/import.t while
we're in the area to use xqx instead of spawn/popen_rd.

3 years agosearchidxshard: replace index_raw with index_eml
Eric Wong [Sun, 3 Jan 2021 02:06:14 +0000 (02:06 +0000)]
searchidxshard: replace index_raw with index_eml

Since Storable and Sereal are designed for lossless
serialization, we'll just pass $eml objects to whatever process
is running SearchIdx.

3 years agosearchidxshard: IPC conversion, part 2
Eric Wong [Sun, 3 Jan 2021 02:06:13 +0000 (02:06 +0000)]
searchidxshard: IPC conversion, part 2

We can remove some now-pointless wrapper functions by using
->ipc_do in even more places.

3 years agosearchidxshard: use PublicInbox::IPC to kill lots of code
Eric Wong [Sun, 3 Jan 2021 02:06:12 +0000 (02:06 +0000)]
searchidxshard: use PublicInbox::IPC to kill lots of code

It's nice to prove the new code works by swapping it into
the current V2Writable / SearchIdxShard packages.  This is
only the first step for the core bits, and we'll be able
to delete more code in a subsequent patch.

3 years agoipc: some documentation comments
Eric Wong [Sun, 3 Jan 2021 02:06:11 +0000 (02:06 +0000)]
ipc: some documentation comments

Fix some comments and add some short summary descriptions to
hopefully make things easier-to-follow.

3 years agogcf2client: split out request API from regular git
Eric Wong [Sun, 3 Jan 2021 02:12:06 +0000 (12:12 -1400)]
gcf2client: split out request API from regular git

While Gcf2Client is designed to mimic what git-cat-file writes
to stdout, its request format is different to support requests
with a git repository path included.

We'll highlight the distinction and make the GitAsyncCat support
code easier-to-follow as a result.

Since Gcf2Client relies on DS, we can rely on DS-specific code
here, too, and use a single Unix socket instead of separate
input and output pipes, reducing memory overhead in both users
and kernel space.  Due to the interactive nature of requests and
responses, the buffer size limitations of Unix sockets on Linux
seems inconsequential here (just like it is for existing "git
cat-file --batch" use).

3 years agolei: fix output race in client/daemon mode
Eric Wong [Sun, 3 Jan 2021 11:24:51 +0000 (11:24 +0000)]
lei: fix output race in client/daemon mode

The daemon needs to flush stdout before disconnecting or killing
clients, otherwise they may reread empty data on redirected
outputs.  We also don't want to unbuffer stdout too early in
case we have lots of small chunks of data to output.

The received ($self->{2}) will always have autoflush, matching normal
STDERR behavior.

3 years agosend and receive all 3 FDs at once
Eric Wong [Sun, 3 Jan 2021 11:24:50 +0000 (11:24 +0000)]
send and receive all 3 FDs at once

We'll always be transferring stdin, stdout, and stderr together
for lei.  Perhaps I lack imagination or foresight, but I can't
think of a reason to send more or less FDs.