about summary refs log tree commit homepage
path: root/lib/PublicInbox/DS.pm
DateCommit message (Collapse)
2019-06-24ds: always use EV_ADD with EV_SET
kqueue EV_ONESHOT semantics are different than epoll EPOLLONESHOT. epoll only disables watches for that event while keeping the item in the rbtree for future EPOLL_CTL_MOD. kqueue removes the watch from the filter set entirely, necessitating the use of EV_ADD for future modifications.
2019-06-24ds: allow ->write callbacks to syswrite directly
We can bypass buffering when wbuf is empty when it's called from a CODE reference passed to ->write.
2019-06-24nntp: call SSL_shutdown in normal cases
This is in accordance with TLS standards and will be needed to support session caching/reuse in the future. However, we don't issue shutdown(2) since we know not to inadvertantly share our sockets with other processes.
2019-06-24ds|nntp: use CORE::close on socket
IO::Socket::SSL will try to re-bless back to the original class on TLS negotiation failure. Unfortunately, the original class is 'GLOB', and re-blessing to 'GLOB' takes away all the IO::Handle methods, because Filehandle/IO are a special case in Perl5. Anyways, since we already use syswrite() and sysread() as functions on our socket, we might as well use CORE::close(), as well (and it plays nicely with tied classes).
2019-06-24nntp: NNTPS and NNTP+STARTTLS working
It kinda, barely works, and I'm most happy I got it working without any modifications to the main NNTP::event_step callback thanks to the DS->write(CODE) support we inherited from Danga::Socket.
2019-06-24ds: deal better with FS-related errors IO buffers
Instead of ENOMEM (or fragmentation/swap storms), using tempfile buffers opens us up to filesystem and storage-related errors (e.g. ENOSPC, EFBIG, EIO, EROFS). Log these errors, drop the particular client, and try to limp by with whateve we have left.
2019-06-24allow use of PerlIO layers for filesystem writes
It may make sense to use PerlIO::mmap or PerlIO::scalar for DS write buffering with IO::Socket::SSL or similar (since we can't use MSG_MORE), so that means we need to go through buffering in userspace for the common case; while still being easily compatible with slow clients. And it also simplifies GitHTTPBackend slightly. Maybe it can make sense for HTTP input buffering, too...
2019-06-24ds: hoist out do_read from NNTP and HTTP
Both NNTP and HTTP have common needs and we can factor out some common code to make dealing with IO::Socket::SSL easier.
2019-06-24ds: remove pointless exit calls
They're never called; the only way to break out of that loop is the PostEventLoop callback.
2019-06-24ds: pass $self to code references
We can reduce the amount of short-lived anonymous subs we create by passing $self to code references.
2019-06-24ds: favor `delete' over assigning fields to `undef'
This is cleaner in most cases and may allow Perl to reuse memory from unused fields. We can do this now that we no longer support Perl 5.8; since Danga::Socket was written with struct-like pseudo-hash support in mind, and Perl 5.9+ dropped support for pseudo-hashes over a decade ago.
2019-06-24ds: get rid of event_watch field
We don't need to keep track of that field since we always know what events we're interested in when using one-shot wakeups.
2019-06-24ds: remove IO::Poll support (for now)
It may be reinstated at a later time if there's interest; but I want to be able to use one-shot notifications for certain events while retaining level-triggered notifications others. OTOH, I intend to fully support kqueue; via IO::KQueue for now, but via syscall() eventually to take advantage of the syscall reduction kevent(2) can provide over (current) epoll APIs.
2019-06-24ds: share watch_chg between watch_read/watch_write
There was much duplicate logic between watch_read and watch_write. Share that logic, and give us room to enable edge-triggered or one-shot notifications in the future.
2019-06-24ds: import IO::KQueue namespace
Make the rest of our IO::KQueue-using code less verbose and closer to the C equivalent.
2019-06-24ds: set event flags directly at initialization
We can avoid the EPOLL_CTL_ADD && EPOLL_CTL_MOD sequence with a single EPOLL_CTL_ADD.
2019-06-24ds: get rid of redundant and unnecessary POLL* constants
EPOLL* constants already match their POLL* counterparts and there's no way Linux can ever diverge or change the values of those constants. So we'll favor the EPOLL* ones since we use EPOLLEXCLUSIVE, already. For weird stuff like kqueue, we'd need to keep maintaining the mapping, anyways.
2019-06-24ds: switch write buffering to use a tempfile
Data which can't fit into a generously-sized socket buffer, has no business being stored in heap.
2019-06-24ds: share send(..., MSG_MORE) logic
No sense in having similar Linux-specific functionality in both our NNTP.pm and HTTP.pm
2019-06-24ds: remove support for DS->write(undef)
We call ->flush_write directly, now; so we can eliminate a needless check.
2019-06-24ds: don't pass `events' arg to EPOLL_CTL_DEL
There's no point in passing a mask of interesting events when removing an item from the epoll watch set.
2019-06-24ds: lazy-initialize wbuf
We don't need write buffering unless we encounter slow clients requesting large responses. So don't waste a hash slot or (empty) arrayref for it.
2019-06-24ds: split out from ->flush_write and ->write
Get rid of the confusing $need_queue variable and all the associated documentation for it. Instead, make it obvious that we're either skipping the write buffer or flushing the write buffer by splitting the sub in two.
2019-06-24ds: lazy initialize wbuf_off
Since Perl 5.10+, "fields" makes a restricted hash; not a compile-time-defined array (struct) with fixed offsets as it did in Perl <= 5.8. Thus in-use fields cost memory, and since the write buffer offset is rarely needed; stop relying on it.
2019-06-24ds: get rid of on_incomplete_write wrapper
Wrong place to be wrapping this method.
2019-06-24AddTimer: avoid clock_gettime for the '0' case
We rely on immediate timers often, so we can avoid the overhead of an extra subroutine call to retrieve the monotonic time (and a sometimes-system call on some platforms).
2019-06-24ds: use and export monotonic now()
All of our internal timing code should use monotonic clocks for consistency against system clock adjustments. This can be shared by our Daemon and NNTP packages.
2019-06-24ds: get rid of more unused debug instance methods
Over a decade of using Danga::Socket and I never found the built-in debug functionality useful.
2019-06-24ds: get rid of {closed} field
Merely checking the presence of the {sock} field is enough, and having multiple sources of truth increases confusion and the likelyhood of bugs.
2019-06-16ds: stop distinguishing event read and write callbacks
Having separate read/write callbacks in every class is too confusing to my easily-confused mind. Instead, give every class an "event_step" callback which is easier to wrap my head around. This will make future code to support IO::Socket::SSL-wrapped sockets easier-to-digest, since SSL_write() can require waiting on POLLIN events, and SSL_read() can require waiting on POLLOUT events.
2019-06-10ds: stop caring about event flags set by epoll/poll/kqueue
If we got something to write, then write it. Otherwise, try reading; and continue dealing with errors which normally occur along the way. Trying to read requests while we need to buffer in luserspace is suicidal from a memory management standpoint. The only adjustment needed for existing callers is EvCleanup; where we need to ensure we're always calling the dummy EvCleanup::event_write callback to accomplish nothing.
2019-06-10ds: do not distinguish between POLLHUP and POLLERR
In my experience, both are worthless as any normal read/write call path will be wanting to check errors and deal with them appropriately; so we can just call event_read, for now. Eventually, there'll probably be only one callback for dealing with all in/out/err/hup events to simplify logic, especially w.r.t TLS socket negotiation.
2019-06-10ds: remove read method, here, too
Since we stop using it in NNTP, we don't need it at all.
2019-06-10ds: remove steal_socket method
We won't be needing it, not even for TLS support.
2019-06-10ds: remove {fd} field
Storing the file descriptor was redundant as we can quickly call fileno($self->{sock}) and not have to store an extra hash table entry. Multiple sources of truth leads to confusion, confusion leads to bugs.
2019-06-10ds: reduce Errno imports and drop ->close reason
ECONNRESET and EPIPE are common on a big Internet filled with unreliable connections, and there's nothing our code can do about it. So no point in wasting code to log them and there are plenty of tracing tools to choose from if such diagnostics are needed.
2019-06-10ds: cleanup Errno imports and favor constant comparisons
Stop importing unused constants, and favor integer comparisons of `$!' over `$!{EFOO}' hash lookups. Integer comparisons are slightly faster, even: Benchmark: timing 30 iterations of cmp_eq, cmp_ne, hash_hit, hash_miss... cmp_eq: 1 wallclock secs ( 1.61 usr + 0.00 sys = 1.61 CPU) @ 18.63/s (n=30) cmp_ne: 2 wallclock secs ( 1.57 usr + 0.00 sys = 1.57 CPU) @ 19.11/s (n=30) hash_hit: 4 wallclock secs ( 3.85 usr + 0.00 sys = 3.85 CPU) @ 7.79/s (n=30) hash_miss: 4 wallclock secs ( 3.74 usr + 0.00 sys = 3.74 CPU) @ 8.02/s (n=30) #!/usr/bin/perl -w use Benchmark qw(:all); use Errno qw(EAGAIN EINTR); my ($r, $w); pipe($r, $w) or die 'pipe'; require IO::Handle; $r->blocking(0); my $buf; my $n = 30000; timethese(30, { hash_hit => sub { sysread($r, $buf, 1); for (0..$n) { next if $!{EAGAIN}; die 'FAIL'; } } , 'cmp_eq' => sub { sysread($r, $buf, 1); for (0..$n) { next if $! == EAGAIN; die 'FAIL'; } }, hash_miss => sub { sysread($r, $buf, 1); for (0..$n) { die 'FAIL' if $!{EINTR}; } }, 'cmp_ne' => sub { sysread($r, $buf, 1); for (0..$n) { die 'FAIL' if $! == EINTR; } }, });
2019-06-10ds: simplify write buffer accounting
Keeping track of write_buf_size was redundant and pointless when we can simply check the number of elements in the buffer array. Multiple sources of truth leads to confusion; confusion leads to bugs. Finally, rename the prefixes to 'wbuf' to ensure we loudly (instead of silently) break any external dependencies being ported over from Danga::Socket, as further changes are pending.
2019-06-03ds: remove PLCMap and per-socket PostLoopCallback
We don't need and won't be needing per-socket PostLoopCallbacks.
2019-06-02ds: drop write_set_watch field
We never enable write watches ourselves for HTTP and NNTP, and only enable the write watch with EvCleanup because it's an "always on" watch.
2019-06-02ds: drop unused EVENT: label in epoll code path
This was never used in Danga::Socket 1.61, either.
2019-06-02ds: drop checks for invalid descriptors
I've used Danga::Socket for well over a decade in various projects at this point and have never seen the need for it. If such a bug ever happens; the process should fall over so it gets fixed ASAP.
2019-06-02ds: drop set_writer_func support
This is not used by perlbal for OpenSSL support, either; and it does not appear to be the right layer for doing write translations anyways (IO::Socket::SSL uses `tie').
2019-06-02ds: add a note about planned future changes
Sometimes I get bored with the email part of this project and need a distraction :P
2019-06-02ds: drop more unused subs
ToClose and HaveEpoll are of no use to us and I see no future use for them, either.
2019-06-01ds: 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.
2019-06-01ds: set close-on-exec flag on epoll descriptors
We should not be leaking these FDs to git(1) processes, in case git has a bug that causes it to access the wrong FD.
2019-05-22DS: warn on deprecations
Enabling deprecation warnings didn't seem to have any noticeable effects with "perl -w -c", so whatever reason Danga had for it is long irrelevant.
2019-05-22DS: remove IPPROTO_TCP import
Unlike Danga::Socket, we do not support TCP_CORK, either
2019-05-22DS: drop $VERSION var
It was only relevant to Danga::Socket.