about summary refs log tree commit homepage
path: root/lib/PublicInbox/Daemon.pm
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-06-24 02:52:54 +0000
committerEric Wong <e@80x24.org>2019-06-24 05:26:27 +0000
commitfbcd2b5eb401a8e1811d803cef9b1c156acb50f6 (patch)
tree508abd361276280bd5d53be46f92b4167309d215 /lib/PublicInbox/Daemon.pm
parent4e1a84c2a97c319862c960a34e3a7a8bf31d5274 (diff)
downloadpublic-inbox-fbcd2b5eb401a8e1811d803cef9b1c156acb50f6.tar.gz
Similar to TCP_DEFER_ACCEPT on Linux, FreeBSD has a 'dataready'
accept filter which we can use to reduce wakeups when doing
TLS negotiation or plain HTTP.  There's also a 'httpready'
which we can use for plain HTTP connections.
Diffstat (limited to 'lib/PublicInbox/Daemon.pm')
-rw-r--r--lib/PublicInbox/Daemon.pm23
1 files changed, 15 insertions, 8 deletions
diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm
index 8b59b65f..cf011a20 100644
--- a/lib/PublicInbox/Daemon.pm
+++ b/lib/PublicInbox/Daemon.pm
@@ -8,7 +8,8 @@ use warnings;
 use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
 use IO::Handle;
 use IO::Socket;
-use Socket qw(IPPROTO_TCP);
+use Socket qw(IPPROTO_TCP SOL_SOCKET);
+sub SO_ACCEPTFILTER () { 0x1000 }
 use Cwd qw/abs_path/;
 STDOUT->autoflush(1);
 STDERR->autoflush(1);
@@ -553,20 +554,25 @@ sub tls_start_cb ($$) {
         }
 }
 
-sub defer_accept ($) {
+sub defer_accept ($$) {
+        my ($s, $af_name) = @_;
+        return unless defined $af_name;
         if ($^O eq 'linux') {
-                my ($s) = @_;
                 my $x = getsockopt($s, IPPROTO_TCP, Socket::TCP_DEFER_ACCEPT());
                 return unless defined $x; # may be Unix socket
                 my $sec = unpack('i', $x);
                 return if $sec > 0; # systemd users may set a higher value
                 setsockopt($s, IPPROTO_TCP, Socket::TCP_DEFER_ACCEPT(), 1);
+        } elsif ($^O eq 'freebsd') {
+                my $x = getsockopt($s, SOL_SOCKET, SO_ACCEPTFILTER);
+                return if defined $x; # don't change if set
+                my $accf_arg = pack('a16a240', $af_name, '');
+                setsockopt($s, SOL_SOCKET, SO_ACCEPTFILTER, $accf_arg);
         }
-        # TODO FreeBSD accf_http / accf_data
 }
 
-sub daemon_loop ($$$) {
-        my ($refresh, $post_accept, $nntpd) = @_;
+sub daemon_loop ($$$$) {
+        my ($refresh, $post_accept, $nntpd, $af_default) = @_;
         PublicInbox::EvCleanup::enable(); # early for $refresh
         my %post_accept;
         while (my ($k, $v) = each %tls_opt) {
@@ -599,7 +605,7 @@ sub daemon_loop ($$$) {
 
                 # NNTPS, HTTPS, HTTP, and POP3S are client-first traffic
                 # NNTP and POP3 are server-first
-                defer_accept($_) if $tls_cb || !$nntpd;
+                defer_accept($_, $tls_cb ? 'dataready' : $af_default);
 
                 # this calls epoll_create:
                 PublicInbox::Listener->new($_, $tls_cb || $post_accept)
@@ -612,8 +618,9 @@ sub daemon_loop ($$$) {
 sub run ($$$;$) {
         my ($default, $refresh, $post_accept, $nntpd) = @_;
         daemon_prepare($default);
+        my $af_default = $default =~ /:8080\z/ ? 'httpready' : undef;
         daemonize();
-        daemon_loop($refresh, $post_accept, $nntpd);
+        daemon_loop($refresh, $post_accept, $nntpd, $af_default);
 }
 
 sub do_chown ($) {