From: Eric Wong <e@80x24.org>
To: yahns-public@yhbt.net
Subject: [PATCH 2/2] wbuf_lite: fix write retries for OpenSSL sockets
Date: Mon, 6 Jun 2016 05:14:21 +0000 [thread overview]
Message-ID: <20160606051421.7082-3-e@80x24.org> (raw)
In-Reply-To: <20160606051421.7082-1-e@80x24.org>
OpenSSL can't handle write retries if we append to an existing
string. Thus we must preserve the same string object upon
retrying.
Do that by utilizing the underlying Wbuf class which could
already handles it transparently using trysendfile.
However, we still avoiding the subtlety of wbuf_close_common
reliance we previously used.
ref: commit 551e670281bea77e727a732ba94275265ccae5f6
("fix output buffering with SSL_write")
---
lib/yahns/wbuf_lite.rb | 46 ++++++++++++++++--------------------
test/test_proxy_pass_no_buffering.rb | 7 +++++-
2 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/lib/yahns/wbuf_lite.rb b/lib/yahns/wbuf_lite.rb
index 5f25b2e..afee1e9 100644
--- a/lib/yahns/wbuf_lite.rb
+++ b/lib/yahns/wbuf_lite.rb
@@ -2,49 +2,43 @@
# Copyright (C) 2016 all contributors <yahns-public@yhbt.net>
# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
# frozen_string_literal: true
-require_relative 'wbuf_common'
+require_relative 'wbuf'
# This is only used for "proxy_buffering: false"
-class Yahns::WbufLite # :nodoc:
- include Yahns::WbufCommon
+class Yahns::WbufLite < Yahns::Wbuf # :nodoc:
attr_reader :busy
def initialize(req_res)
+ super(nil, :ignore)
@req_res = req_res
- @busy = false
- @buf = nil
end
- # called only by proxy_write in proxy_http_response
def wbuf_write(client, buf)
- buf = buf.join if Array === buf
- buf = @buf << buf if @buf # unlikely
- do_write(client, buf) # try our best to avoid string copying/appending
+ super
+ rescue
+ @req_res = @req_res.close if @req_res
+ raise
end
- def do_write(client, buf)
- case rv = client.kgio_trywrite(buf)
- when String
- buf = rv # continue looping
- when :wait_writable, :wait_readable
- @buf = buf
- return @busy = rv
- when nil
- @buf = nil
- return @busy = false
- end while true
+ def wbuf_flush(client)
+ super
+ rescue
+ @req_res = @req_res.close if @req_res
+ raise
end
# called by Yahns::HttpClient#step_write
- def wbuf_flush(client)
- sym = do_write(client, @buf) and return sym # :wait_writable/:wait_readable
+ def wbuf_close(client)
+ wbuf_abort
- # resume reading
- client.hijack_cleanup
- Thread.current[:yahns_queue].queue_mod(@req_res, Yahns::Queue::QEV_RD)
+ # resume reading when @blocked is empty
+ if @req_res
+ client.hijack_cleanup
+ Thread.current[:yahns_queue].queue_mod(@req_res, Yahns::Queue::QEV_RD)
+ end
:ignore
rescue
- @req_res.close
+ @req_res = @req_res.close if @req_res
raise
end
end
diff --git a/test/test_proxy_pass_no_buffering.rb b/test/test_proxy_pass_no_buffering.rb
index 48b8241..b2c8b48 100644
--- a/test/test_proxy_pass_no_buffering.rb
+++ b/test/test_proxy_pass_no_buffering.rb
@@ -79,6 +79,7 @@ def test_proxy_pass_no_buffering
req = "GET /giant-body HTTP/1.1\r\nHost: example.com\r\n" \
"Connection: close\r\n\r\n"
s.write(req)
+ bufs = []
sleep 1
10.times do
sleep 0.1
@@ -91,10 +92,14 @@ def test_proxy_pass_no_buffering
[ deleted1, deleted2 ].each do |ary|
ary.delete_if { |x| x =~ /\.(?:err|out) \(deleted\)/ }
end
- assert_equal 0, deleted1.size, "pid1=#{deleted1.inspect}"
+ assert_equal 1, deleted1.size, "pid1=#{deleted1.inspect}"
assert_equal 0, deleted2.size, "pid2=#{deleted2.inspect}"
+ bufs.push(deleted1[0])
end
end
+ before = bufs.size
+ bufs.uniq!
+ assert bufs.size < before, 'unlinked buffer should not grow'
buf = ''.dup
slow = Digest::MD5.new
ft = Thread.new do
prev parent reply other threads:[~2016-06-06 5:14 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-06 5:14 [YUCK 0/2] wbuf_lite: fix write retries for OpenSSL Eric Wong
2016-06-06 5:14 ` [PATCH 1/2] wbuf: remove tmpdir parameter Eric Wong
2016-06-06 5:14 ` Eric Wong [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://yhbt.net/yahns/README
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160606051421.7082-3-e@80x24.org \
--to=e@80x24.org \
--cc=yahns-public@yhbt.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://yhbt.net/yahns.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).