about summary refs log tree commit homepage
DateCommit message (Collapse)
2015-12-04README: clarify and update copyright year
This is no place to advertise weirdo projects.
2015-12-01test_wbuf: deal with proper zero-copy for Unix sockets
Linux 4.2 gained the ability to do true zero-copy sendfile support for Unix sockets; so buffer space is accounted differently. Previously Linux only avoided copies in userspace when doing sendfile for Unix sockets, not internally within the kernel. This kernel change has no bearing on normal code which would need to account for concurrent draining by the client; only test code designed to create a failure condition.
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-11-01yahns 1.10.0 - minor updates v1.10.0
* test_client_expire: favor Process.spawn over fork+exec * extras/try_gzip_static: require readability on HEAD requests * proxy_pass: quiet down ECONNRESET and EPIPE, too * copyright updates * update various comments * proxy_http_response: use frozen string literal optimization * README: add link to NNTP archive endpoint * use olddoc 1.1.0 for generating NEWS + NEWS.atom.xml * gemspec fixes for various RubyGems versions * bytecode golfing to cut a few bytes of memory * simplify sd_listen_fds emulation * gemspec: allow compatibility with unicorn 5
2015-11-01gemspec: allow compatibility with unicorn 5
We've been compatible for a while, actually, and probably could've done this earlier. We won't be dropping unicorn 4.x compatibility for a bit in case some folks need to stick to unicorn 4.x for any reason.
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-28gemspec fixes for various RubyGems versions
Version may not be frozen in some RubyGems versions, so we must dup it. Use a SPDX-compatible license string for GPL-3.0+, too (RubyGems still complains, for now)
2015-10-15use olddoc 1.1.0 for generating NEWS + NEWS.atom.xml
This removes the build-time dependency on Nokogiri, which can be time-consuming to install. We won't be supporting any public APIs, so we will not actually support RDoc here.
2015-10-14README: add link to NNTP archive endpoint
The service seems stable and reliable enough to advertise in our README.
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-08-14extras/try_gzip_static: require readability on HEAD requests
Files may exist and be stat-able, but not readable. Return a 403 response for non-readable files.
2015-07-21test_client_expire: favor Process.spawn over fork+exec
Process.spawn is faster under Linux since it may use vfork to avoid marking pages copy-on-write.
2015-07-21yahns 1.9.0 - minor updates v1.9.0
This release improves socket inheritance support. TCP socket options are now applied to inherited sockets. We also emulate the sd_listen_fds function to allow inheriting sockets from systemd. HTTP status strings are now generated dynamically, allowing applications to modify Rack::Utils::HTTP_STATUS_CODES to apply changes in the Rack response. Unfortunately, this leads to minor (likely unnoticeable) performance regressions. However, our code is not optimized for Ruby 2.2+, so users on the latest released Ruby will benefit from reduced inline cache and constant lookups as we reduced our constant footprint. Expect further minor performance regressions if you are running Ruby 2.2 and earlier. For Ruby 2.2 users, overall performance should be largely unchanged from 1.7.0 to 1.8.0 shortlog of changes since 1.7.0: * use opt_str_freeze for Hash#delete * test/helper: warn atomically * generate response status strings dynamically * reduce constants and optimize for Ruby 2.2+ * http_response: reduce bytecode size * apply TCP socket options on inherited sockets * test/test_rack_hijack.rb: try to increase test reliability * emulate sd_listen_fds for systemd support * test/test_rack_hijack: ensure proper ordering of log messages
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-17test/test_rack_hijack: ensure proper ordering of log messages
Getting the logs to show up in order is tricky in a multithreaded server...
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-15test/test_rack_hijack.rb: try to increase test reliability
We need to wait for the hijacked process to run and write to the log before we check it. Since we may not have inotify, try to trigger a sched_yield() syscall instead.
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-15test/helper: warn atomically
We want to avoid race conditions if tests become multithreaded from Kernel#warn internally issuing a second write.
2015-06-11yahns 1.8.0 - minor updates v1.8.0
Most notably, the Rack response body is now closed during rack.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 We'll also support SIGWINCH 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. A few more minor changes, more memory reduction changes coming... * proxy_pass: no point in closing StringIO * proxy_pass: allow filtering or overriding response headers * support SIGWINCH even if not daemonized * use Unicorn::HttpParser#response_start_sent accessor * reduce inline constant cache overheads * proxy_pass: skip tests if kcar is missing * ensure body is closed during hijack
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-10proxy_pass: skip tests if kcar is missing
We don't require kcar to be installed since most users will never use the proxy_pass feature, but show an informative error in case they want to test this functionality.
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-11yahns 1.7.0 - rack.hijack improvements and more v1.7.0
Nothing really significant, so there's no need to upgrade if you're not affected by the minor fixes and changes in this release. For all users, LoadError and SyntaxError exceptions are now logged and non-fatal within worker threads serving application code. Thanks to Lin Jen-Shin <godfat@godfat.org> for bringing this up on the mailing list. Additionally, temporary files buffered to the filesystem will now support the Rack::TempfileReaper middleware in rack 1.6+ For rack.hijack users, there are some changes and improvements. rack.hijack should return a usable IO-like object for SSL users, now. The rack.input object is no longer closed on hijacking, allowing apps to continue using buffered input after hijacking. There is also a bugfix for the rare apps which hijack requests after emitting 100-continue responses. Note: there is also a work-in-progress and under-documented asynchronous Yayns::ProxyPass Rack app which uses rack.hijack internally. This will allow yahns to act as a fully-buffering reverse proxy to upstream servers which cannot handle slow clients. Yahns::ProxyPass NOT production-ready as of this release. The old, synchronous extras/proxy_pass.rb code remains usable. There's also the usual round of minor code bloat reduction.
2015-05-11extras/proxy_pass: remove compatibility note
We'll have to support both, it seems.
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).
2015-04-24proxy_pass: clear backtrace on ECONNREFUSED
Bad connections or dead upstreams cannot be solved looking at a backtrace, so avoid polluting logs with them and making other problems less visible.
2015-04-22favor #nil? instead of "== nil" comparisons in cold code
We don't need optimized dispatch methods in cold code, so use the more space-efficient "nil?" method dispatch to save us one word per-call site for a rough total of 24 bytes saving.
2015-04-22config: avoid unnecessary binmode call
We may set binary mode upon open by passing "b" in the mode string, so avoid the extra method dispatch and bytecode/cache overhead that entails.
2015-04-21proxy_pass: fix race condition due to flawed hijack check
The entire idea of a one-shot-based design is all the mutual exclusion is handled by the event dispatch mechanism (epoll or kqueue) without burdening the user with extra locking. However, the way the hijack works means we check the Rack env for the 'rack.hijack_io' key which is shared across requests and may be cleared. Ideally, this would not be a problem if the Rack dispatch allowed returning a special value (e.g. ":ignore") instead of the normal status-headers-body array, much like what the non-standard "async.callback" API Thin started. We could also avoid this problem by disallowing our "unhijack-ing" of the socket but at a significant cost of crippling code reusability, including that of existing middleware. Thus, we allocate a new, empty request object here to avoid a TOCTTOU in the following timeline: original thread: | another thread HttpClient#yahns_step | r = k.app.call(env = @hs.env) # socket hijacked into epoll queue <thread is scheduled away> | epoll_wait readiness | ReqRes#yahns_step | proxy dispatch ... | proxy_busy_mod_done ************************** DANGER BELOW ******************************** | HttpClient#yahns_step | # clears env # sees empty env: | return :ignore if env.include?('rack.hijack_io') | In other words, we cannot ever touch the original env seen by the original thread since it must see the 'rack.hijack_io' value because both are operating in the same Yahns::HttpClient object. This will happen regardless of GVL existence. Avoiding errors like this is absolutely critical to every one-shot based design.
2015-04-11proxy_pass: attempt to forward premature upstream responses
Upstreams may shut us down while we're writing a request body, attempt to forward any responses from the upstream back to the client which may explain the rejection reason for giant uploads.