about summary refs log tree commit homepage
path: root/lib
DateCommit message (Collapse)
2009-04-12Save one fcntl() syscall on every request
MRI 1.8 always sets O_NONBLOCK on sockets to implement green threads correctly in the face of slow network I/O. Since we already know what the I/O flags for a client socket should be, we just set it to that instead. Applications running on Unicorn continue to be green thread-safe when used fast local traffic. Of course, Unicorn itself will never use threads.
2009-04-11Remove _all_ non-POSIX socket options
Unicorn is strictly for fast LAN and localhost clients. Unicorn is not for slow, high-latency or trickling clients and cannot do keepalive or pipelining. None of the removed options actually make sense in the environment Unicorn was designed for. * DEFER_ACCEPT/ACCEPT_FILTER - these are useful for mitigating connect() floods or trickling clients. We shouldn't have to deal with those on a trusted LAN. * TCP_CORK/TCP_NODELAY - we only send output in the response and then immediately close the socket. Assuming the typical response containing a small header and large strings in the body: the Nagle algorithm would've corked the headers regardless and any pending output would be immediately flushed when the socket is closed immediately after sending. These options would still be useful from the client-side on the LAN, or if Unicorn supported keepalive. Of course, I highly recommend enabling all of these options you can possibly enable on nginx or another fully-buffering reverse proxy when dealing with slow clients.
2009-04-10listen backlog, sndbuf, rcvbuf are always changeable
Apparently I was smoking crack and thought they weren't changeable. Additionally, SO_REUSEADDR is set by TCPServer.new, so there's no need to set it ourselves; so avoid putting extra items in the purgatory. This allows SIGHUP to change listen options.
2009-04-10Restore unlinked UNIX sockets on SIGHUP
Sockets may be unintentionally unlinked on the filesystem. When reloading our config, ensure that the socket exists on the filesystem. If not, close the listener (since it's unusable by outside apps) and reopen it.
2009-04-10config: handle listener unbind/replace in config file
Rather than blindly appending to our listener set with every "listen" directive read in the config file, reset our internal array. Listeners specified on the command-line are always preserved between config reloads.
2009-04-10close listeners when removing them from our array
This fixes a long-standing bug where listeners would be removed from the known listener set during a reload but never correctly shut down (until reexec). Additionally, test_server was working around this bug (my fault, subconciously) as teardown did not unbind the socket, requiring the tests to grab a new port.
2009-04-08http11: handle "X-Forwarded-Proto: https"
Pass "https" to "rack.url_scheme" if the X-Forwarded-Proto header matches "https". X-Forwarded-Proto is a semi-standard header that Ruby frameworks seem to respect; so we use that. We won't support ENV['HTTPS'] since that can only be set at start time and some app servers supporting https also support http. Currently, "rack.url_scheme" only allows "http" and "https", so we won't set anything else to avoid breaking Rack::Lint.
2009-04-07cleanup some log messages
* no need to show PID of process writing the logs, the default log formatter already includes it * Don't bother displaying classes of listeners, the address themselves should be enough.
2009-04-05Enforce umask 0000 with UNIX domain sockets
I can't think of a good reason to ever use restrictive permissions with UNIX domain sockets for an HTTP server. Since some folks run their nginx on port 80 and then have it drop permissions, we need to ensure our socket is readable and writable across the board. The reason I'm respecting the existing umask at all (instead of using 0000 across the board like most daemonizers) is because the admin may want to restrict access (especially write access) to log files.
2009-04-03configurator: allow hooks to be passed callable objects
Premade lambda/proc/Proc objects may all be passed, to the hooks, not just anonymous blocks.
2009-04-02unicorn 0.4.2 v0.4.2
2009-04-02Use File.basename instead of a regexp
Just because I know regular expressions doesn't mean I *have* to use them...
2009-04-02More descriptive process titles
Multiple Unicorn applications one machine can get confusing quickly. Regardless, make it easy to distinguish between workers and the master process.
2009-04-01Close std{err,out} redirection targets
The newly open file descriptors live on as fd=1 and fd=2 anyways, so there's no reason to keep duplicates around.
2009-04-01FD_CLOEXEC all non-listen descriptors before exec
We'll allow before_exec to override that setting, however. There are cases where someone setting Logger.new("/path/to/file") will create new file descriptors in the master process. This will prevent FD leakage and a test case (for Linux only) proves it.
2009-04-01All IOs created in workers have FD_CLOEXEC set
Prevent subtle leaks here, too.
2009-04-01Remove set_cloexec wrapper and require FD_CLOEXEC
FD_CLOEXEC is POSIX and we only run on POSIX. Things will slowly leak over time if FD_CLOEXEC is not set, so raise the issue ASAP.
2009-04-01unicorn 0.4.1 v0.4.1
2009-04-01cgi_wrapper: HTTP status code cleanups
The default status was 404 in Mongrel and this is needed to work with older versions of Rails. Additionally parse the "Status:" header if it ever got set and the actual "status" code passed to CGI::headers was not set.
2009-04-01cgi_wrapper: fix cookies and other headers
The @output_cookies instance variable was being ignored, and some versions of Rails uses that. Additionally, cleanup multi-value headers in general to avoid dropping headers.
2009-03-31Use {read,write}_nonblock on the pipe
Instead of trusting sysread/syswrite to throw EAGAIN if the pipe is full (highly unlikely); just use non-blocking methods which are indeed non-blocking and don't care for the #blocking= method added to it.
2009-03-31configurator: remove unnecessary SocketHelper include
2009-03-31Better canonicalization of listener paths + tests
* Expand addresses like "1:8080" to "127.0.0.1:8080" beforehand so sock_name() in SocketHelper will always return consistent results. * Add support for "unix:/path/to/foo" paths for easier synchronization with nginx config files.
2009-03-30cgi_wrapper: ensure "Status:" header is not set
Rack does not like it; instead try to set it as the @status code if possible.
2009-03-30app/old_rails/static: define missing constant
REQUEST_METHOD got removed from Unicorn::Const and this module is the only place that currently uses it.
2009-03-29Fix default listener setup
Combining command-line and config file options in a reasonable manner has and always will be a painful experience.
2009-03-29Avoid having two pid files pointing to the same pid
It makes test_exec more reliable and probably helps other scripts people may run around this.
2009-03-29http11: use :http_body instead of "HTTP_BODY"
"HTTP_BODY" could conflict with a "Body:" HTTP header if there ever is one. Also, try to hide this body from the Rack environment before @app is called since it is only used by Unicorn internally.
2009-03-29configurator: favor "listen" directive over "listeners"
We still need to support "listeners" for easy use of command-line options, but folks using the config file should use "listen" as it is more flexible.
2009-03-29configurator: per-listener backlog, {rcv,snd}buf config
Instead of having global options for all listeners, make all socket options per-listener. This allows reverse-proxies to pick different listeners to get different options on different sockets. Given a cluster of machines (10.0.0.1, 10.0.0.2, 10.0.0.3) running Unicorn with the following config: ------------------ 8< ---------------- listen "/tmp/local.sock", :backlog => 1 listen "*:8080" # use the backlog=1024 default ------------------ 8< ---------------- It is possible to configure a reverse proxy to try to use "/tmp/local.sock" first and then fall back to using the TCP listener on port 8080 in a failover configuration. Thus the nginx upstream configuration on 10.0.0.1 to compliment this would be: ------------------ 8< ---------------- upstream unicorn_cluster { # reject connections ASAP if we are overloaded server unix:/tmp/local.sock; # fall back to other machines in the cluster via "backup" # listeners which have a large backlog queue. server 10.0.0.2:8080 backup; server 10.0.0.3:8080 backup; } ------------------ 8< ---------------- This removes the global "backlog" config option which was inflexible with multiple machines in a cluster and exposes the ability to change SO_SNDBUF/SO_RCVBUF via setsockopt(2) for the first time.
2009-03-27Always try to send a valid HTTP response back
This reworks error handling throughout the entire stack to be more Ruby-ish. Exceptions are raised instead of forcing the us to check return values. If a client is sending us a bad request, we send a 400. If unicorn or app breaks in an unexpected way, we'll send a 500. Both of these last-resort error responses are sent using IO#write_nonblock to avoid tying Unicorn up longer than necessary and all exceptions raised are ignored. Sending a valid HTTP response back should reduce the chance of us from being marked as down or broken by a load balancer. Previously, some load balancers would mark us as down if we close a socket without sending back a valid response; so make a best effort to send one. If for some reason we cannot write a valid response, we're still susceptible to being marked as down. A successful HttpResponse.write() call will now close the socket immediately (instead of doing it higher up the stack). This ensures the errors will never get written to the socket on a successful response.
2009-03-27Remove needless line break
2009-03-27No need to disable luserspace buffering on client socket
Unicorn always uses lower-level sys{read,write} methods when doing I/O so setting "client.sync=true" is just a wasted operation.
2009-03-27style: symbols instead of strings for signal names
They're easier for me to type and read and just barely faster when doing comparisons on.
2009-03-27Deferred log rotation in workers
Instead of rotating logs immediately when SIGUSR1 is caught, defer it until the current client is processing is complete. This allows multi-line log messages generated by apps to not be broken up if SIGUSR1 is received while the app is running. If we're sleeping inside IO.select, we close a pipe in the exceptfds set to cause EBADF to be raised. This also adds a small reliability improvement to test_exec so we wait until signals are ready before sending USR1 to rotate logs.
2009-03-26Don't allow failed log rotation to to break app
In case there are permissions problems that cause log rotation to fail, we trap the error and defer death until the current request finishes running.
2009-03-25Merge commit 'v0.2.3'
* commit 'v0.2.3': unicorn 0.2.3 Ensure Tempfiles are unlinked after every request Don't bother unlinking UNIX sockets Conflicts: lib/unicorn/socket.rb
2009-03-25unicorn 0.2.3 v0.2.3
2009-03-25Ensure Tempfiles are unlinked after every request
Otherwise we bloat TMPDIR and run the host out of space, oops!
2009-03-25Don't bother unlinking UNIX sockets
Since we always unlink existing sockets when binding, there's no point in having code to unlink the sockets when we exit. Additionally, the old code path was racy.
2009-03-25Socket: add {snd,rcv}buf opts to bind_listen
bind_listen takes a hash as its second parameter now, allowing the addition of :sndbuf and :rcvbuf options to specify the size of the buffers in bytes. These correspond to the SO_SNDBUF and SO_RCVBUF options via setsockopt(2) respectively. This also adds support for per-listener backlogs to be used. However, this is only an internal API change and the changes have not yet been exposed to the user via Unicorn::Configurator, yet. Also add a bunch of SocketHelper tests
2009-03-24simplify the HttpParser interface
This cuts the HttpParser interface down to #execute and #reset method. HttpParser#execute will return true if it completes and false if it is not. http->nread state is kept internally so we don't have to keep track of it in Ruby; removing one parameter from #execute. HttpParser#reset is unchanged. All errors are handled through exceptions anyways, so the HttpParser#error? method stopped being useful. Also added some more unit tests to the HttpParser since I know some folks are (rightfully) uncomfortable with changing stable C code. We now have tests for incremental parsing. In summary, we have: * more test cases * less C code * simpler interfaces * small performance improvement => win \o/
2009-03-24HttpRequest: small improvement for GET requests
Most HTTP requests are GET requests and the majority of those GET requests are complete after one sysread. This is especially true since we're optimized for fast clients. So short the extra checks and trust our HTTP parser implementation to do the right thing (we have decent unit tests for it).
2009-03-23unicorn_rails: support non-Rack versions of Rails
This resurrects old code from Mongrel to wrap the Rails Dispatcher for older versions of Rails. It seems that Rails >= 2.2.0 support Rack, but only >=2.3 requires it. I'd like to support Rails 1.2.x for a while, too.
2009-03-22Don't bother unlinking UNIX sockets
Since we always unlink existing sockets when binding, there's no point in having code to unlink the sockets when we exit. Additionally, the old code path was racy.
2009-03-22Streamline rack environment generation
Ensure constants are used as hash keys and cleanup unused constants. This gives a 10-15% improvement with test/benchmark/request.rb
2009-03-22HttpResponse: speed up non-multivalue headers
The extra split slows things down a little as as it generates an array with a new string value and adds an extra loop to iterate through.
2009-03-22unicorn 0.2.2 v0.2.2
2009-03-21Handle Rack multivalue headers correctly
Rack uses a single newline character to represent multi-value headers. Thus { 'Set-Cookie' => "foo=bar\nbar=foo" } will get you: Set-Cookie: foo=bar Set-Cookie: bar=foo While RFC2616 says you can combine headers as: Set-Cookie: foo=bar,bar=foo There are probably HTTP clients out there that don't handle things correctly so don't bother... Additionally, don't bother doing duplicate suppression anymore. Just assume Rack or a higher layer knows what it's doing regarding duplicates and we'll get a Hash most of the time anyways.
2009-03-21Simplify code for sleeping/waking up the master
Only sleep if our signal queue is empty. Remove redundant exception handling and go back to just consuming the entire pipe since that's more efficient if we're slammed with signals for whatever reason.