about summary refs log tree commit homepage
path: root/lib
DateCommit message (Collapse)
2016-04-27proxy_pass: drop resources immediately on errors
We don't want to wait on GC to reap sockets on errors, generational GC in Ruby is less aggressive about reaping long-lived objects such as long-lived HTTP connections.
2016-04-27proxy_http_response: do not persist upstream on slow clients
For slow clients, we want to be able to drop the connection to the upstream as soon as we are done buffering and not waste resources by leaving it in an :ignore state. We also need to remember the client for the fdmap to prevent shutdowns. Ugh, this is really hard to test locally.
2016-04-27proxy_http_response: cleanup: avoid redundant setting of "alive"
We already check for the truthiness of "alive" in the "if" statement, so re-setting is pointless.
2016-04-27wbuf: drop persistence if writing to client fails
We cannot maintain a persistent connection to a client if writing to the client fails; so we can't proceed to let the app hijack the response. This may happen in the unlikely case where a response header needs to be buffered with a Wbuf (and the app uses response hijacking).
2016-04-23proxy_http_response: fix non-terminated fast responses, too
Without this, non-terminated backends were not properly supported if they gave tiny responses or responded faster than we could stream the response to the client. This is necessary to support fast responses from some non-Rack HTTP/1.0-only backend servers which rely on connection termination to terminate responses. Tested manually with a Perl PSGI application running under "plackup". Unlike Rack, the PSGI spec does not specify whether the PSGI application or PSGI server should handle response termination: git clone https://github.com/plack/psgi-specs.git Follow-up-to: 8c9f33a5396d2 ("workaround non-terminated backends")
2016-04-23proxy_pass: honor wbuf_persist when ending response
If a static file response gets truncated while writing, we set wbuf_persist to false in wbuf_flush of lib/yahns/wbuf_common.rb Thus, we must check wbuf_persist attribute as late as possible before yielding control back to the caller in proxy_response_finish
2016-04-06proxy_http_response: workaround non-terminated backends
Without this, we could only support persistent connections if the backend gives a valid Content-Length or set "Transfer-Encoding: chunked" in the response header. Being good netizens, we want to use persistent connections as much as possible if a remote client supports it; so perform chunking ourselves when our remote clients are HTTP/1.1 and able to decode chunked responses. This is necessary to support some non-Rack HTTP/1.0-only backend servers which rely on connection termination to terminate responses. Tested manually with a Perl PSGI application running under "plackup". Unlike Rack, the PSGI spec does not specify whether the PSGI application or PSGI server should handle response termination: git clone https://github.com/plack/psgi-specs.git
2016-02-29ssl: ensure is session_id_context is always set
When a client attempts to reuse a session, we must have a session_id_context set or else handshakes fail. This problem manifests only with clients which attempt to reuse stored sessions. This is irrespective of any session caching configured (even if explicitly disabled) in the server. The SSL_CTX_set_session_id_context(3SSL) manpage states: If the session id context is not set on an SSL/TLS server and client certificates are used, stored sessions will not be reused but a fatal error will be flagged and the handshake will fail.
2016-02-20https: ensure SERVER_PORT defaults to 443
This helps Rack::Request#url and similar methods generate proper URLs instead of the obviously wrong: "https://example.com:80/" Note: we don't track the actual port the listener is bound to, and it may not be worth it since the use of the Host: header is long-established and Host: headers include the port number if non-standard.
2016-02-20fix output buffering with SSL_write
The underlying SSL_write called by the OpenSSL socket when we use write_nonblock must get the same arguments after a call returns SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. Ensure that by always passing a copy of the user-supplied buffer to OpenSSL::SSL::SSLSocket#write_nonblock and retaining our copy of the string internally as @ssl_blocked if we hit EAGAIN on the socket. String#dup is inexpensive in modern Ruby, as copying a non-embedded string is implemented using copy-on-write. We also prefer to use write_nonblock directly instead of using our kgio-dependent sendfile emulation layer to avoid allocating a new string on partial writes. ref: https://bugs.ruby-lang.org/issues/12085 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/73882 http://mid.gmane.org/redmine.issue-12085.20160219020243.4b790a77f1cdd593@ruby-lang.org
2016-02-14http_context: reduce constant lookup + bytecode
This saves about 100 bytes of iseq overhead based on my measurements.
2016-02-13proxy_pass: pass X-Forwarded-Proto through
This allows backend application servers to set "rack.url_scheme" as appropriate using Rack::Request#scheme. Plack/PSGI users can also take advantage of this using Plack::Middleware::ReverseProxy
2016-02-12set HTTPS and rack.url_scheme in Rack env as appropriate
env['HTTPS'] is not documented in rack SPEC, but appears to be used by Rack::Request since 2010[*]. Also, set rack.url_scheme as documented by rack SPEC. [*] - commit 4defbe5d7c07b3ba721ff34a8ff59fde480a4a9f ("Improves performance by lazy loading the session.")
2016-02-12avoid race conditions in OpenSSL::SSL::SSLContext#setup
By explicitly calling OpenSSL::SSL::SSLContext#setup before accepting connections. We cannot rely on "setup" being called implicitly because any callbacks configured or objects configured by the client may not be thread-safe. We also avoid calling "setup" in the master process (if yahns is configured to use worker processeses) in case the setup code starts any TCP connections (e.g. to memcached for session caching).
2016-02-12properly emulate sendfile for OpenSSL sockets
We cannot use the sendfile(2) syscall when serving static files to TLS clients without breaking them. We currently rely on OpenSSL to encrypt the data before it hits the socket, so it must be read into userspace buffers before being written to the socket.
2016-02-12acceptor: all subclasses of TCPServer use TCP_INFO
This will allow Yahns::OpenSSLServer instances to take advantage of TCP_INFO under Linux, saving us the overhead of method invocations.
2016-01-04use String#clear for short-lived buffers we create
This should reduce memory pressure slightly as we can have finer-grained control of memory usage for buffers which can be several kilobytes large. It is not safe to do this for output buffers we get from the application, as they may reuse that memory themselves.
2016-01-04avoid StringIO#binmode for the next few years
Apparently, StringIO#binmode has been totally broken in 1.9+ and I've always hidden this bug with the combination of an explicit string and magic "encoding: binary" comments :x ref: https://bugs.ruby-lang.org/issues/11945
2016-01-02copyright updates for 2016
Using the 'update-copyright' script from gnulib[1]: git ls-files | UPDATE_COPYRIGHT_HOLDER='all contributors' \ UPDATE_COPYRIGHT_USE_INTERVALS=2 \ xargs /path/to/gnulib/build-aux/update-copyright We're also switching to 'GPL-3.0+' as recommended by SPDX to be consistent with our gemspec and other metadata (as opposed to the longer but equivalent "GPLv3 or later"). [1] git://git.savannah.gnu.org/gnulib.git
2016-01-02enable frozen_string_literal for Ruby 2.3+
There are likely yet-to-be-discovered bugs in here. Also, keeping explicit #freeze calls for 2.2 users, since most users have not migrated to 2.3, yet.
2015-12-15nodoc internals
We do not expose any sort of API beyond what's in the config file manpage to our users. Do not mislead them into thinking we currently have a stable API (though I'm considering one). This avoids wasting disk space and installation time for users who do not have a: "gem: --no-ri --no-rdoc" line in their ~/.gemrc
2015-12-13openssl_client: use `exception: false' for accept_nonblock
Ruby 2.3 will support this feature to reduce allocations for common errors.
2015-12-01wbuf: fix typo in bug check for sendfile gem
This typo would've only be triggered if the sendfile gem itself turns out to be buggy and returns an undocumented return code.
2015-10-28simplify sd_listen_fds emulation
Remove unnecessary anonymous procs and conditionals to save some bytecode memory Also, no valid PID can be zero, as kill(2) treats zero specially.
2015-10-28bytecode golfing to cut a few bytes of memory
Reduce unnecessary arguments to "exit" and "exit!". Additionally, rely on a "putnil" instruction rather than a "putstring" argument with an unnecessary string operand for an uncommon code path.
2015-10-13proxy_http_response: use frozen string literal optimization
This can reduce the amount of garbage we have by a small amount. Once Ruby 2.3 comes out, we can rely on the "frozen_string_literal: true" directive
2015-10-13update various comments
Clarify APP_CONFIG is only public for modules maintained within yahns, not external users. While we're at it, avoid the http:// -> https:// redirect for bugs.ruby-lang.org in the comment.
2015-10-13copyright updates
Future updates may use the update-copyright script in gnulib: git ls-files | UPDATE_COPYRIGHT_HOLDER='all contributors' \ UPDATE_COPYRIGHT_USE_INTERVALS=2 \ xargs /path/to/gnulib/build-aux/update-copyright
2015-10-03proxy_pass: quiet down ECONNRESET and EPIPE, too
Clients may disconnect on us while we're writing the response here, so we should shut the backtrace up to avoid polluting logs.
2015-07-21use opt_str_freeze for Hash#delete
Unfortunately we cannot rely on the RubyVM for optimizing hash deletions, yet, so manually freeze for this string since it (unlike every line after it) is a hot path if handling request bodies. Update a comment while we're at it.
2015-07-15emulate sd_listen_fds for systemd support
systemd socket emulation shares FDs across execve, just like the built-in SIGUSR2 upgrade process in unicorn. Thus it is easy to support inheriting sockets from systemd.
2015-07-03apply TCP socket options on inherited sockets
TCP socket options are now set when inheriting existing sockets from a parent process. I'm fairly certain all the TCP setsockopt knobs we use are idempotent and harmless to change. If anything, the only directive I'd be uncomfortable changing is shortening the listen(2) (aka :backlog) size, but we've always changed that anyways since it also applies to UNIX sockets. Note: removing a configuration knob in a yahns config file can not reset the value to the OS-provided default setting. Inherited sockets must use a new setting to override existing ones. (or the socket needs to be closed and re-created in the process launcher before yahns inherits it). Based on unicorn commit 1db9a8243d42cc86d5ca4901bceb305061d0d212 Noticed-by: Christos Trochalakis <yatiohi@ideopolis.gr> <20150626114129.GA25883@luke.ws.skroutz.gr>
2015-06-30http_response: reduce bytecode size
This saves around 200 bytes on x86-64 and potentially improves CPU cache performance. This does not reduce inline method cache overhead as String#<< already has optimized dispatch support (opt_ltlt in insns.def in Ruby 1.9+)
2015-06-30reduce constants and optimize for Ruby 2.2+
Ruby (MRI) 2.1 optimizes allocations away on String#freeze with literal strings. Furthermore, Ruby 2.2 optimizes away literal string allocations when they are used as arguments to Hash#[] and Hash#[]= Thus we can avoid expensive constant lookups and cache overhead by taking advantage of advancements in Ruby. Since Ruby 2.2 has been out for 7 months, now; it ought to be safe to introduce minor performance regressions for folks using older Rubies (1.9.3+ remains supported) to benefit folks on the latest Ruby.
2015-06-30generate response status strings dynamically
Rack::Utils::HTTP_STATUS_CODES may be altered by the underlying application, allow changes to that to be reflected in our responses and do not rely on the Unicorn::HttpResponse::CODES hash which will probably go away soon.
2015-06-10ensure body is closed during hijack
Middlewares such as Rack::Lock (used by Rails) break badly unless the response body is closed on hijack, so we will close it to follow the lead of other popular Rack servers. While it's unclear if there's anybody using rack.hijack besides yahns/proxy_pass we'll try to emulate the behavior of other servers as much as possible. ref: https://github.com/ngauthier/tubesock/issues/10 While we're at it, use DieIfUsed correctly in test_ssl.rb :x
2015-06-05reduce inline constant cache overheads
We can use symbols in the SleepyPenguin APIs to trade speed for space in uncommon code paths.
2015-06-05use Unicorn::HttpParser#response_start_sent accessor
We don't need to waste a valuable ivar slot on each socket when we know unicorn already maintains this flag for us.
2015-06-05support SIGWINCH even if not daemonized
This has no effect for the (default) single process case with no master/worker relationship as that does not support SIGWINCH. Some process managers such as foreman and daemontools rely on yahnsnot daemonizing, but we still want to be able to process SIGWINCH in that case. stdout and stderr may be redirected to a pipe (for cronolog or similar process), so those are less likely to be attached to a TTY than stdin. This also allows users to process SIGWINCH when running inside a regular terminal if they redirect stdin to /dev/null. This follows unicorn commit a6077391bb62d0b13016084b0eea36b987afe8f0 Thanks to Dan Moore for suggesting it on the unicorn list.
2015-05-18proxy_pass: allow filtering or overriding response headers
We shouldn't blindly pass the "Server" tag through, since we may be proxying Apache instances and we don't want to misadvertise, either. IMHO, it is best to say nothing at all to save bandwidth and reduce the potential for attackers in case a vulnerability is discovered in yahns.
2015-05-12proxy_pass: no point in closing StringIO
It does not release memory immediately and GC can handle it reliably, so don't waste a constant lookup + cache entry on it. While we're at it, explain why we can't do a simpler respond_to? check instead.
2015-05-11worker threads log LoadError and SyntaxError, too
Some applications may lazily load code during app dispatch, triggering LoadError or SyntaxError exceptions. Log the error and backtrace so application maintainers can more easily notice and diagnose problems. Keep in mind users are likely to have performance and race condition problems with lazy loading, and the process may still be in a bad state due to partially-loaded code. This commit is only intended to give application authors a chance to notice and fix or avoid problems in the future. Note: logging fatal exceptions by default in all threads was proposed in ruby-core, but currently not implemented in any released version: https://bugs.ruby-lang.org/issues/6647 Reported-by: Lin Jen-Shin (godfat) <godfat@godfat.org> <CAA2_N1umJO12XH9r+JHnA6r=z=Mwp_PqOrdnW65oqW2K2-iAoQ@mail.gmail.com>
2015-05-09support for Rack::TempfileReaper middleware
Rack::TempfileReaper was added in rack 1.6 to cleanup temporary files. Make Yahns::TmpIO ducktype-compatible and put it into env['rack.tempfiles'] array so Rack::TempfileReaper may be used to free up space used by temporary buffer files. ref: commit 3bdf5481e49d76b4502c51e5bdd93f68bfd1f0b4 in unicorn
2015-05-09proxy_pass: favor literal hash over arrays for error responses
Arrays are less verbose, but they have more bytecode overhead which actually matters at runtime.
2015-05-09ssl: ensure rack.hijack users get "normal" IO methods
We do not want rack.hijack users relying on kgio_* methods since kgio is trying to make itself obsolete (as Ruby itself adopts kgio features). This is a bit wonky since our common case tries to minimize object allocation by only using the Kgio::Socket derived class.
2015-05-09openssl_client: remove shutdown call
OpenSSL::SSL::SSLSocket does not actually respond to a shutdown method, and it would not be safe to call anyways. Merely shutdown at the OS level and let any handling thread clean it up.
2015-05-08avoid excess allocations for rack.hijack support
Proc object allocation is not cheap, so avoid doing it and allow Yahns::HttpClient to be assigned as the env["rack.hijack"] callback for Rack applications.
2015-05-08proxy_pass: avoid unnecessary close method
No point in wasting space and reducing code clarity with this method to remove references to live objects.
2015-05-08proxy_pass: fix race condition due to ensure
When calling proxy_busy_mod_blocked to re-enable a descriptor via epoll, the ensure block is dangerous because the "ensure" clause modifies the object after the ReqRes is injected into epoll. This is extremely dangerous as we give up exclusive access to the object once we call epoll_ctl. This simplifies the code a bit while we're at it.
2015-05-08proxy: ensure GC sees the client socket upon reactivation
Reactivating a client socket after the proxied response is complete requires the object remain visible to the Ruby GC while no thread is accessing it. So we must place the object back into the fdmap to prevent the GC from eating it (and having epoll return an invalid pointer).