user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [PATCH 06/11] ds: consolidate IO::Socket::SSL checks
  2019-06-29 19:59  7% [PATCH 00/11] ds: more updates Eric Wong
@ 2019-06-29 19:59  6% ` Eric Wong
  0 siblings, 0 replies; 2+ results
From: Eric Wong @ 2019-06-29 19:59 UTC (permalink / raw)
  To: meta

We need to be careful about handling EAGAIN on write(2)
failures deal with SSL_WANT_READ vs SSL_WANT_WRITE as
appropriate.
---
 lib/PublicInbox/DS.pm   | 48 +++++++++++++++++++++++++-----------------------
 lib/PublicInbox/NNTP.pm |  3 ++-
 lib/PublicInbox/TLS.pm  |  9 +++------
 3 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/lib/PublicInbox/DS.pm b/lib/PublicInbox/DS.pm
index 6cd527e2..b2f59983 100644
--- a/lib/PublicInbox/DS.pm
+++ b/lib/PublicInbox/DS.pm
@@ -388,6 +388,10 @@ sub psendfile ($$$) {
     $written;
 }
 
+sub epbit ($$) { # (sock, default)
+    ref($_[0]) eq 'IO::Socket::SSL' ? PublicInbox::TLS::epollbit() : $_[1];
+}
+
 # returns 1 if done, 0 if incomplete
 sub flush_write ($) {
     my ($self) = @_;
@@ -406,8 +410,8 @@ next_buf:
                         goto next_buf;
                     }
                 } elsif ($! == EAGAIN) {
+                    epwait($sock, epbit($sock, EPOLLOUT) | EPOLLONESHOT);
                     $self->{wbuf_off} = $off;
-                    watch($self, EPOLLOUT|EPOLLONESHOT);
                     return 0;
                 } else {
                     return $self->close;
@@ -438,17 +442,13 @@ sub rbuf_idle ($$) {
 
 sub do_read ($$$;$) {
     my ($self, $rbuf, $len, $off) = @_;
-    my $r = sysread($self->{sock}, $$rbuf, $len, $off // 0);
+    my $r = sysread(my $sock = $self->{sock}, $$rbuf, $len, $off // 0);
     return ($r == 0 ? $self->close : $r) if defined $r;
     # common for clients to break connections without warning,
     # would be too noisy to log here:
-    if (ref($self) eq 'IO::Socket::SSL') {
-        my $ev = PublicInbox::TLS::epollbit() or return $self->close;
+    if ($! == EAGAIN) {
+        epwait($sock, epbit($sock, EPOLLIN) | EPOLLONESHOT);
         rbuf_idle($self, $rbuf);
-        watch($self, $ev | EPOLLONESHOT);
-    } elsif ($! == EAGAIN) {
-        rbuf_idle($self, $rbuf);
-        watch($self, EPOLLIN | EPOLLONESHOT);
     } else {
         $self->close;
     }
@@ -525,17 +525,20 @@ sub write {
 
         if (defined $written) {
             return 1 if $written == $to_write;
+            requeue($self); # runs: event_step -> flush_write
         } elsif ($! == EAGAIN) {
+            epwait($sock, epbit($sock, EPOLLOUT) | EPOLLONESHOT);
             $written = 0;
         } else {
             return $self->close;
         }
+
+        # deal with EAGAIN or partial write:
         my $tmpio = tmpio($self, $bref, $written) or return 0;
 
         # wbuf may be an empty array if we're being called inside
         # ->flush_write via CODE bref:
         push @{$self->{wbuf} ||= []}, $tmpio;
-        watch($self, EPOLLOUT|EPOLLONESHOT);
         return 0;
     }
 }
@@ -554,32 +557,34 @@ sub msg_more ($$) {
             # queue up the unwritten substring:
             my $tmpio = tmpio($self, \($_[1]), $n) or return 0;
             $self->{wbuf} = [ $tmpio ];
-            watch($self, EPOLLOUT|EPOLLONESHOT);
+            epwait($sock, EPOLLOUT|EPOLLONESHOT);
             return 0;
         }
     }
     $self->write(\($_[1]));
 }
 
-sub watch ($$) {
-    my ($self, $ev) = @_;
-    my $sock = $self->{sock} or return;
+sub epwait ($$) {
+    my ($sock, $ev) = @_;
     epoll_ctl($Epoll, EPOLL_CTL_MOD, fileno($sock), $ev) and
         confess("EPOLL_CTL_MOD $!");
     0;
 }
 
+sub watch ($$) {
+    my ($self, $ev) = @_;
+    my $sock = $self->{sock} or return;
+    epwait($sock, $ev);
+}
+
 # return true if complete, false if incomplete (or failure)
 sub accept_tls_step ($) {
     my ($self) = @_;
     my $sock = $self->{sock} or return;
     return 1 if $sock->accept_SSL;
     return $self->close if $! != EAGAIN;
-    if (my $ev = PublicInbox::TLS::epollbit()) {
-        unshift @{$self->{wbuf} ||= []}, \&accept_tls_step;
-        return watch($self, $ev | EPOLLONESHOT);
-    }
-    drop($self, 'BUG? EAGAIN but '.PublicInbox::TLS::err());
+    epwait($sock, PublicInbox::TLS::epollbit() | EPOLLONESHOT);
+    unshift @{$self->{wbuf} ||= []}, \&accept_tls_step;
 }
 
 sub shutdn_tls_step ($) {
@@ -587,11 +592,8 @@ sub shutdn_tls_step ($) {
     my $sock = $self->{sock} or return;
     return $self->close if $sock->stop_SSL(SSL_fast_shutdown => 1);
     return $self->close if $! != EAGAIN;
-    if (my $ev = PublicInbox::TLS::epollbit()) {
-        unshift @{$self->{wbuf} ||= []}, \&shutdn_tls_step;
-        return watch($self, $ev | EPOLLONESHOT);
-    }
-    drop($self, 'BUG? EAGAIN but '.PublicInbox::TLS::err());
+    epwait($sock, PublicInbox::TLS::epollbit() | EPOLLONESHOT);
+    unshift @{$self->{wbuf} ||= []}, \&shutdn_tls_step;
 }
 
 # don't bother with shutdown($sock, 2), we don't fork+exec w/o CLOEXEC
diff --git a/lib/PublicInbox/NNTP.pm b/lib/PublicInbox/NNTP.pm
index 9973fcaf..82762b1a 100644
--- a/lib/PublicInbox/NNTP.pm
+++ b/lib/PublicInbox/NNTP.pm
@@ -75,7 +75,8 @@ sub new ($$$) {
 	my $ev = EPOLLIN;
 	my $wbuf;
 	if (ref($sock) eq 'IO::Socket::SSL' && !$sock->accept_SSL) {
-		$ev = PublicInbox::TLS::epollbit() or return CORE::close($sock);
+		return CORE::close($sock) if $! != EAGAIN;
+		$ev = PublicInbox::TLS::epollbit();
 		$wbuf = [ \&PublicInbox::DS::accept_tls_step, \&greet ];
 	}
 	$self->SUPER::new($sock, $ev | EPOLLONESHOT);
diff --git a/lib/PublicInbox/TLS.pm b/lib/PublicInbox/TLS.pm
index 576c11d7..0b9a55df 100644
--- a/lib/PublicInbox/TLS.pm
+++ b/lib/PublicInbox/TLS.pm
@@ -13,12 +13,9 @@ sub err () { $SSL_ERROR }
 
 # returns the EPOLL event bit which matches the existing SSL error
 sub epollbit () {
-	if ($! == EAGAIN) {
-		return EPOLLIN if $SSL_ERROR == SSL_WANT_READ;
-		return EPOLLOUT if $SSL_ERROR == SSL_WANT_WRITE;
-		die "unexpected SSL error: $SSL_ERROR";
-	}
-	0;
+	return EPOLLIN if $SSL_ERROR == SSL_WANT_READ;
+	return EPOLLOUT if $SSL_ERROR == SSL_WANT_WRITE;
+	die "unexpected SSL error: $SSL_ERROR";
 }
 
 1;
-- 
EW


^ permalink raw reply related	[relevance 6%]

* [PATCH 00/11] ds: more updates
@ 2019-06-29 19:59  7% Eric Wong
  2019-06-29 19:59  6% ` [PATCH 06/11] ds: consolidate IO::Socket::SSL checks Eric Wong
  0 siblings, 1 reply; 2+ results
From: Eric Wong @ 2019-06-29 19:59 UTC (permalink / raw)
  To: meta

We can simplify a lot of our async logic now that we don't have
to deal with the buffer-to-heap behavior of Danga::Socket.

The biggest change is now we no longer tie git-http-backend(1)
runtime and memory use to the bandwidth of a slow HTTP client.
This increases buffering on the FS (which may be tmpfs or
a fast SSD); but it's what nginx (and varnish) would be doing,
anyways

We can further remove a lot of the EvCleanup code since that
was to workaround deferred close being deferred for too long
when no I/O events were firing.

HTTPS now works, but more work needs to be done because
Varnish is still a requirement for busy sites.

Eric Wong (11):
  ds: share lazy rbuf handling between HTTP and NNTP
  ds: move requeue logic over from NNTP
  http: use requeue instead of watch_in1
  listener: use edge-triggered notifications
  ds: handle deferred DS->close after timers
  ds: consolidate IO::Socket::SSL checks
  http: support HTTPS (kinda)
  parentpipe: document and use one-shot wakeups
  parentpipe: make the ->close call more obvious
  httpd/async: switch to buffering-as-fast-as-possible
  http: use bigger, but shorter-lived buffers for pipes

 MANIFEST                       |   1 +
 lib/PublicInbox/DS.pm          |  85 +++++++++++++++----------
 lib/PublicInbox/DSKQXS.pm      |   4 +-
 lib/PublicInbox/Daemon.pm      |   4 +-
 lib/PublicInbox/EvCleanup.pm   |  80 +++--------------------
 lib/PublicInbox/HTTP.pm        | 102 +++++++++++++++--------------
 lib/PublicInbox/HTTPD/Async.pm |  55 ++++++++--------
 lib/PublicInbox/Listener.pm    |   7 +-
 lib/PublicInbox/NNTP.pm        |  47 +++-----------
 lib/PublicInbox/ParentPipe.pm  |  17 +++--
 lib/PublicInbox/Qspawn.pm      |   2 +-
 lib/PublicInbox/Syscall.pm     |   4 +-
 lib/PublicInbox/TLS.pm         |   9 +--
 t/httpd-https.t                | 141 +++++++++++++++++++++++++++++++++++++++++
 14 files changed, 314 insertions(+), 244 deletions(-)
 create mode 100644 t/httpd-https.t

-- 
EW


^ permalink raw reply	[relevance 7%]

Results 1-2 of 2 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2019-06-29 19:59  7% [PATCH 00/11] ds: more updates Eric Wong
2019-06-29 19:59  6% ` [PATCH 06/11] ds: consolidate IO::Socket::SSL checks Eric Wong

Code repositories for project(s) associated with this public inbox

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).