about summary refs log tree commit homepage
path: root/lib/PublicInbox/Spawn.pm
DateCommit message (Collapse)
2021-10-23cmd_ipc4: retry sendmsg on ENOBUFS/ENOMEM/ETOOMANYREFS
I'm seeing ENOBUFS on a RAM-starved system, and slowing the sender down enough for the receiver to drain the buffers seems to work. ENOMEM and ETOOMANYREFS could be in the same boat as ENOBUFS. Watching for POLLOUT events via select/poll/epoll_wait doesn't seem to work, since the kernel can already sleep (or return EAGAIN) for cases where POLLOUT would work.
2021-09-14spawn+gcf2: improve diagnostics for build failures
I'm not sure why, but I noticed the one of my latest restarts of public-inbox-httpd wasn't loading the Inline::C .so for Gcf2 nor Spawn. I also can't reproduce the problem as both .so files are loaded fine on a restart with zero config changes. In any case, some extra, automatic diagnostics for build errors won't hurt, as no extra noise is introduced for successful builds. This will also make future development of C code more convenient, hopefully.
2021-02-24treewide: avoid "delete local" construct on hashes
Apparently this feature is only in Perl 5.12+, and we're still on Perl 5.10.
2021-02-07spawn: pi_fork_exec: support "pgid"
We'll be using this to allow the "git clone" process hierarchy to be killed via Ctrl-C. This also fixes a long-standing bug in error reporting for the Inline::C version, because we're actually testing for errors, now! n.b. strlen(3) is officially async-signal-safe as of POSIX.1-2016, but I can't think of a reason any previous implementation prior to that wouldn't be.
2021-02-07spawn: pi_fork_exec: restore parent sigmask in child
We continue to unblock SIGCHLD unconditionally, but also any signals not blocked by the parent (wq_worker). This will allow Ctrl-C (SIGINT) to stop "git clone" and allow git-clone cleanup to be performed and other long-running processes when pi_fork_exec supports setpgid(2). This won't affect existing daemons on systems with signalfd(2) or EVFILT_SIGNAL at all, since those run with signals blocked anyways.
2021-02-04spawn: merge common C code together
There'll probably be more things which work on both GNU and *BSD systems which we don't need separate strings for.
2021-01-30lei: less error-prone FD mapping
Keeping track of non-standard FDs gets tricky, so make it easier by relying on st_dev/st_ino mapping in the transmitted objects. We'll keep using numbers for the standard FDs since we need to be able to easily redirect them in the producer (main daemon) process for (gzip|bzip2|xz) if writing to a compressed mbox.
2021-01-26use defined-or in a few more places
Mainly around fork() calls, but some nearby places as well.
2021-01-26spawn: split() on regexp, not a literal string
It doesn't appear Perl (as of 5.32.x) has any internal optimization for splitting on a single-byte, so give it a regexp instead of letting it compile and discard a new one every single time.
2021-01-21lei 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.
2021-01-18lei 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.
2021-01-14cmd_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.
2021-01-12lei_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.
2021-01-12ipc: 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.
2021-01-12cmd_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.
2021-01-04lei: 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.
2021-01-03send 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.
2021-01-03spawn: support send_fd+recv_fd w/o IO::FDPass
IO::FDPass may be an extra installation burden I don't want to impose on users. We only support Linux and *BSDs, however.
2021-01-02processpipe: allow synchronous close to set $?
To get rid of the ugly $PublicInbox::DS::in_loop localization in MboxReader, we'll distinguish between ->CLOSE and ->DESTROY with ProcessPipe. If we end up closing via ->DESTROY, we'll assume the caller will want to deal with $? asynchronously via the event loop (or not even care about $?). If we hit ->CLOSE directly, we'll assume the caller called close() and wants to check $? synchronously. Note: wantarray doesn't seem to propagate into tied methods, otherwise I'd be relying on that.
2021-01-01update copyrights for 2021
Using "make update-copyrights" after setting GNULIB_PATH in my config.mak
2021-01-01spawn: move run_die here from PublicInbox::Import
It seems like a more logical place for it, but we'll favor the newly-added xsys_e() in tests for BAIL_OUT use.
2020-08-08support setting No_COW on Perl <5.22
fileno(DIRHANDLE) only works on Perl 5.22+, so we need to use dirfd(3) ourselves from Inline::C (or rely on chattr(1) being installed). While we're at it, rename `set_nodatacow' to `nodatacow_fd' for consistency with `nodatacow_dir'.
2020-08-01improve error handling on import fork / lock failures
v?fork failures seems to be the cause of locks not getting released in -watch. Ensure lock release doesn't get skipped in ->done for both v1 and v2 inboxes. We also need to do everything we can to ensure DB handles, pipes and processes get released even in the face of failure. While we're at it, make failures around `git update-server-info' non-fatal, since smart HTTP seems more popular anyways. v2 changes: - spawn: show failing command - ensure waitpid is synchronous for inotify events - teardown all fast-import processes on exception, not just the failing one - beef up lock_release error handling - release lock on fast-import spawn failure
2020-07-29searchidx: disable CoW for SQLite and Xapian under btrfs
SQLite and Xapian files are written randomly, thus they become fragmented under btrfs with copy-on-write. This leads to noticeable performance problems (and probably ENOSPC) as these files get big. lore/git (v2, <1GB) indexes around 20% faster with this on an ancient SSD. lore/lkml seems to be taking forever and I'll probably cancel it to save wear on my SSD. Unfortunately, disabling CoW also means disabling checksumming (and compression), so we'll be careful to only set the No_COW attribute on regeneratable data. We want to keep CoW (and checksums+compression) on git storage because current ref storage is neither checksummed nor compressed, and git streams pack output.
2020-07-02spawn: drop unused sys/uio.h include
We no longer use writev(2) in pi_fork_exec to emit errors.
2020-07-02spawn: modernize with parent.pm, drop warnings.pm
parent.pm is smaller than base.pm, and we'll also move towards relying on `-w' (or not) to toggle process-wide warnings during development.
2020-07-02spawn: make @RLIMITS an array
Making the RLIMITS list a function doesn't allow constant folding, so just make it an array accessible to other modules.
2020-06-30spawn: unblock SIGCHLD in subprocess
Subprocess we spawn may want to use SIGCHLD for themselves. This also ensures we restore default signal handlers in the pure Perl version.
2020-05-23spawn: fix compatibility with old Inline::C
Older versions of Inline (e.g. 0.53 in CentOS 7) did not accept the `directory' parameter, so use conditional assignment to set a default value on $ENV{PERL_INLINE_DIRECTORY}, instead.
2020-05-12spawn: use ~/.cache/public-inbox/inline-c if writable
Despite several memory reductions and pure Perl performance improvements, Inline::C spawn() still gives us a noticeable performance boost. More user-oriented command-line programs are likely coming, setting PERL_INLINE_DIRECTORY is annoying to users, and so is is poor performance. So allow users to opt-in to using our Inline::C code once by creating a `~/.cache/public-inbox/inline-c' directory. XDG_CACHE_HOME is respected to override the location of ~/.cache independent of HOME, according to https://specifications.freedesktop.org/basedir-spec/0.6/ar01s03.html v2: use "/nonexistent" if HOME is undefined, since that's the home of the "nobody" user on both FreeBSD and Debian.
2020-03-04spawn: correctly handle error code
Both the C and pure Perl implementions of `pi_fork_exec' returns `-1' on error, not `undef'.
2020-02-06treewide: run update-copyrights from gnulib for 2019
I didn't wait until September to do it, this year!
2020-02-02spawn: actually die on (vfork|fork) failures
Commit 9f5a583694396f84 ("spawn (and thus popen_rd) die on failure") was incomplete in that it only removed error checking for spawn failures for non-(vfork|fork) calls, but the actual (vfork|fork) PID result could still be undef. Fixes: 9f5a583694396f84 ("spawn (and thus popen_rd) die on failure")
2020-01-11spawn (and thus popen_rd) die on failure
Most spawn and popen_rd callers die on failure to spawn, anyways, and some are missing checks entirely. This saves us a bunch of verbose error-checking code in callers. This also makes popen_rd more consistent, since it already dies on pipe creation failures.
2020-01-06treewide: "require" + "use" cleanup and docs
There's a bunch of leftover "require" and "use" statements we no longer need and can get rid of, along with some excessive imports via "use". IO::Handle usage isn't always obvious, so add comments describing why a package loads it. Along the same lines, document the tmpdir support as the reason we depend on File::Temp 0.19, even though every Perl 5.10.1+ user has it. While we're at it, favor "use" over "require", since it it gives us extra compile-time checking.
2019-12-30spawn: better error handling
Since vfork always shares memory between the child and parent, we can propagate errors to the parent errno using shared memory instead of just dumping to stderr and hoping somebody sees it.
2019-12-30spawn: support chdir via -C option
This simplifies our admin module a bit and allows solver to be used with v1 inboxes using git versions prior to v1.8.5 (but still >= git v1.8.0).
2019-12-30spawn: allow passing GLOB handles for redirects
We can save callers the trouble of {-hold} and {-dev_null} refs as well as the trouble of calling fileno().
2019-12-24remove "no warnings 'once'" in a few places
We can use "use" to get the namespace into the "BEGIN" phase of the interpreter. While we're at it, use \&coderef syntax explicitly instead of globbing everything.
2019-12-11spawn: remove support for clearing the env
It's unnecessary code which I'm not sure we ever used. In retrospect, completely clearing the environment doesn't make sense for the processes we spawn. We don't need to clobber individual environment variables in our code, either (and if we did for tests, we can use 'local').
2019-11-16spawn: which: allow embedded slash for relative path
This makes the subroutine behave more like which(1) command and will make using spawn() in tests easier.
2019-09-09run update-copyrights from gnulib for 2019
2019-06-24spawn: remove `Blocking' flag handling
Instead, the O_NONBLOCK flag is set by PublicInbox::HTTPD::Async; and we won't be setting it elsewhere.
2019-05-07spawn (Inline::C): fix off-by-one error
Noticed while testing on FreeBSD 11.2 amd64 with the optional Inline::C extension using clang 6.0.0. The end result on FreeBSD was spawning processes failed badly and things were immediately unusable with this enabled. av_len is a misleading API, and I failed to read the API comments in perl:/av.c which state: > Note that, unlike what the name implies, it returns > the highest index in the array, so to get the size of > the array you need to use "av_len(av) + 1". > This is unlike "sv_len", which returns what you would expect. If this bug affected anybody, it would've only affected users using both the optional Inline::C module AND set the PERL_INLINE_DIRECTORY environment variable. That said, I've never seen any evidence of it on Debian GNU/Linux + gcc on any x86 variant. That includes full 64-bit systems, a full 32-bit system, a 64-bit system with 32-bit userspace, across multiple gcc versions since 2016.
2019-04-04spawn: require soft and hard entries in RLIMIT_* handling
Our high-level config already treats single limits as a soft==hard limit for limiters; so stop handling that redundant in the low-level spawn() sub.
2019-04-04qspawn: wire up RLIMIT_* handling to limiters
This allows users to configure RLIMIT_{CORE,CPU,DATA} using our "limiter" config directive when spawning external processes.
2019-04-04spawn: support absolute paths
cgit (and most other CGI executables) is not typically installed for use via $PATH, so we'll need to support absolute paths to run it.
2019-04-04spawn: support RLIMIT_CPU, RLIMIT_DATA and RLIMIT_CORE
We'll be spawning cgit and git-diff, which can take gigantic amounts of CPU time and/or heap given the right (ermm... wrong) input. Limit the damage that large/expensive diffs can cause.
2018-02-07update copyrights for 2018
Using update-copyrights from gnulib While we're at it, use the SPDX identifier for AGPL-3.0+ to ease mechanical processing.
2016-06-21spawn: improve error checking for fork failures
fork failures are unfortunately common when Xapian has gigabytes and gigabytes mmapped.