about summary refs log tree commit homepage
path: root/lib/yahns/server.rb
DateCommit message (Collapse)
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-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-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-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-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-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-02-05use the monotonic clock under Ruby 2.1+
The monotonic clock is immune to time adjustments so it is not thrown off by misconfigured clocks. Process.clock_gettime also generates less garbage on 64-bit systems due to the use of Flonum.
2014-12-02initial cut at OpenSSL support
The current CA model and code quality of OpenSSL have long put me off from supporting TLS; however but efforts such as "Let's Encrypt" and the fallout from Heartbleed give me hope for the future. This implements, as much as possible, a "hands-off" approach to TLS support via OpenSSL. This implementation allows us to shift responsibility away from us to users and upstreams (the Ruby 'openssl' extension maintainers, software packagers, and OpenSSL project itself). This is also perhaps the easiest way for now for us, while being most powerful for users. It requires users to configure their own OpenSSL context object which we'll use as-is. This context object is used as the :ssl_ctx parameter to the "listen" directive in the yahns configuration file: require 'openssl' # we will not do this for the user, even ctx = OpenSSL::SSL::SSLContext.new # user must configure ctx here... listen 443, ssl_ctx: ctx This way, in case we support GnuTLS or other TLS libraries, there'll be less confusion as to what a user is actually using. Note: this feature requires Ruby 2.1 and later for non-kgio {read,write}_nonblock(.. exception: false) support.
2014-11-20favor Array#map! for freshly-split arrays
This barely reduces garbage objects at startup, but less garbage is usually better.
2014-11-18save around 1500 bytes of memory on x86-64
Replacing a Regexp argument to a rarely-called String#split with a literal String can save some memory. Each removed Regexp memsize is 469 bytes on Ruby 2.1, and Ruby does not currently deduplicate literal Regexps. On Ruby 2.1, the "objspace" extension shows: ObjectSpace.memsize_of(/,/) => 469 Is slightly smaller at 453 bytes on 2.2.0dev (r48474), and these numbers do not include the 40-byte object overhead. Nevertheless, this is a waste for non-performance-critical code during the startup phase. Identical literal strings are automatically deduplicated by Ruby 2.1, and has no additional overhead because Rack (and likely some real apps) also includes several instances of the literal "," byte. We'll drop the unnecessary "encoding: binary" magic comment in yahns/server.rb as well, as that file includes no literal binary strings. The downside of using a literal string argument in these cases is a 40-byte object gets allocated on every call, but the affected pieces of code are only called once in a process lifetime.
2014-10-13switch to require_relative for internal requires
This speeds up searching during startup and prevents accidentally misloading different, potentially incompatible versions of yahns code.
2014-05-09rework master-to-worker signaling to use a pipe
This prevents potential errors and compatibility problems with buggy libraries which do not respond well to signal delivery. Based on unicorn commit 6f6e4115b4bb03e5e7c55def91527799190566f2
2014-05-09server: account for premature grandparent death
When daemonizing, it is possible for the grandparent to be terminated by another process before the master can notify it. Do not abort the master in this case. unicorn commit 27ae210dde9228cfa96ea6b0f3a7e4047d3f70a4
2013-11-07fdmap: document + fix for level-trigger
Our QueueQuitter may race with epoll_wait and GC, potentially triggering memory corruption if a level-trigger object was placed into the ready list and no longer referenced. We'll work around this problem by making the QueueQuitter object a thread-local (on thread failure) to prevent concurency issues where the epoll pointer no longer points to a Ruby object.
2013-11-07fdmap: simplify IO expiry interface
The first argument of the old __expire_for method was completely unused in all but one invocation of it, so it is not worth it. This also simplifies the code a bit too.
2013-11-07shutdown_timeout works around long-running response/apps
apps/responses may trickle infinitely, so our QueueQuitter may not properly kill epoll worker threads, unfortunately. So we'll start the timer and stop waiting (risking segfaults/ugliness) by closing epoll descriptors
2013-11-07SIGWINCH works after SIGUSR2 upgrades
We must know we're daemonized after a SIGUSR2 upgrade, even if we don't use the pipe to signal to the controlling terminal we've started up.
2013-11-06server: log error instead of raising for leftover socks
This may happen if we get by a forceful exit, so we'll risk triggering some bugs elsewhere, but forceful exits are never pretty...
2013-11-05server: improve shutdown messages
It may be disconcerting to not know how long it takes a server to gracefully exit, so provide that feedback. While we're at it, avoid dropping acceptors if we want a forceful exit.
2013-11-02worker-less server should not waitpid indiscriminately
We must not reap processes we did not spawn if we're not using a master/worker configuration. This may break applications which depend on waitpid themselves. However we still trap SIGCHLD currently. In the future, we could switch our notification model mode to be compatible with apps which depend on SIGCHLD or might indiscriminately on children (which might prevent us from knowing about SIGCHLD).
2013-11-01remove unnecessary map(&:to_s) before Array#join
Array#join implies string conversion and unicorn has been doing that for ages.
2013-11-01enable client expiry for non-TCP sockets
It's conceivable a sub-optimally configured instance can have too many Unix sockets connected to us. This also implements expiry for systems without sufficient "struct tcp_info" support.
2013-10-31remove "worker_" prefix from atfork hooks
It was totally unnecessary and just made things hard-to-follow.
2013-10-31comment to explain YAHNS_FD env
Users of other web servers may be surprised there is no recommended way to have a new instance of yahns inherit from another web server.
2013-10-31implement before_exec hook
This allows modifying the command-line (as an array) passed to Kernel#exec, as well as running anything necessary.
2013-10-31implement shutdown_timeout and expiry on graceful shutdown
Otherwise, the server may stay running forever if a client chooses to stay forever (and there is no FD pressure).
2013-10-30Rack hijack issues EPOLL_CTL_DEL
This saves about 200 bytes of unswappable kernel memory, so it might matter for systems with many connections when hijacking.
2013-10-30server: fix incorrect receiver of method call
Oops, this was only noticed when inheriting a descriptor we want to close.
2013-10-30allow multiple blocking threads per listen socket
This is probably not needed and just adds contention, but it makes experimenting easier. While we're at it, validate minimum values of for sndbuf/rcvbuf along with this new threads value, too.
2013-10-29server: fix out-of-date comment regarding bind/pid order
Unfortunately, my eyes are more-or-less trained to ignore documentation when I edit code.
2013-10-29implement user switching
This was documented (incorrectly) and not implemented for either the master/worker or single process cases. Implement and test all (with mocks, so not fully-tested).
2013-10-28associate private/anonymous queues correctly
We do not want users to use the default queue unless an app context requires it. We also do not want to spin up the default queue unless we are sure we have app contexts using it (and not private/anonymous queues).
2013-10-26server: avoid metaclass for acceptors
This should make things a little easier-to-follow and possibly improve method cache hit rates for servers with multiple acceptors.
2013-10-26fix SIGCHLD w/o workers + PID file renames
We'll hit SIGCHLD if our reexec process fails on us, so the non-MP server must handle it, too. We discovered this bug while porting the PID file renaming changes from unicorn.
2013-10-25quitter: save one syscall and implement for non-eventfd
pipes and eventfd are always writable after creation, thus there's no need to trigger it and watch for readability. This saves us some code in the Linux case (and we currently only support GNU/Linux).
2013-10-22config: implement atfork handlers
These can be used to disconnect/reconnect to databases and other external connections. These are named to match the documentation of pthread_atfork(3)
2013-10-22server: switch abort to raise on BUG
Having a backtrace would be nice, actually.
2013-10-22server (minor cleanup): use Symbol#to_proc
2013-10-22rework acceptor thread shutdown (again)
Calling close on the socket while accept4 is running on a different thread can be problematic on Rubinius and some versions of MRI. So we will use a thread-local variable, continuously issue new connections to our own socket and rely on the round-robin behavior of accept4 to eventually get our acceptor thread to wakeup. We must continuously issue new connections because some connections may be going to a new processes (from SIGUSR2). We cannot use shutdown for the same reason.
2013-10-22reinstate retry delay for binding new listeners
This could still be useful since new listeners may be newly shut down and the socket is still in the process of being released in the kernel.
2013-10-21server: abort loudly if we have old threads running
Leaving acceptor threads running cause client-visible errors because the last accepted socket may enter (or attempt to enter) the queue before the queue is shutdown. Leaving a worker queue thread running can be problematic, too, since it can trigger bugs in the Ruby implementation (which we'll track down and fix).
2013-10-21server (cleanup): avoid interning word for log message
It will be converted to a string anyways, so do not bother.
2013-10-21server: skip killing acceptors on rbx for now
This seems problematic on rbx (and their bugtracker requiring access to a non-Free SaaS is an inconvenience to me). Also, improve the robustness of our acceptors in case by rescuing Thread#join as well.
2013-10-21wip for EADDRINUSE failure
2013-10-21SIGUSR2 uses fork + exec again instead of Process.spawn
There is no way we can rely on any potential vfork optimization given our use of redirects (vfork only pauses calling thread). This partially reverts commit d973de0d6dfdf799e111d9f9a71170b61a0ac100
2013-10-21rework shutdown for systems w/o rb_thread_fd_close
Acceptors require closing the descriptor, first, and then doing a (nasty) cross-thread exception to kick the thread out of the blocking accept via Thread#run (pthread_kill SIGVTALRM). We cannot do what we're doing with epoll with acceptors because the accept socket is shared across processes. We will also NEVER be using non-blocking accept, as it's more important we fairly distribute connections between tasks when we're not shutting the server down. The queue worker threads are much easier to kill off :) We can simply inject a new QueueQuitter object as a Level-Triggering epoll watch, activate it, and let it wreak havok on all the worker threads from a single event activation. rb_thread_fd_close is convenient, but expensive with many threads, so be prepared for more systems without it. This is for Rubinius compatibility. Yes, we are actually using Level-Triggered epoll here (despite the non-shutdown pieces of our code being based around EPOLLONESHOT).