Date | Commit message (Collapse) |
|
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.
|
|
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.
|
|
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.
|
|
|
|
* 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.
|
|
Rack does not like it; instead try to set it as
the @status code if possible.
|
|
REQUEST_METHOD got removed from Unicorn::Const
and this module is the only place that currently
uses it.
|
|
Combining command-line and config file options in a reasonable
manner has and always will be a painful experience.
|
|
It makes test_exec more reliable and probably helps
other scripts people may run around this.
|
|
"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.
|
|
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.
|
|
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.
|
|
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.
|
|
|
|
Unicorn always uses lower-level sys{read,write} methods
when doing I/O so setting "client.sync=true" is just
a wasted operation.
|
|
They're easier for me to type and read and just barely faster
when doing comparisons on.
|
|
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.
|
|
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.
|
|
* 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
|
|
|
|
Otherwise we bloat TMPDIR and run the host out of space, oops!
|
|
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.
|
|
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
|
|
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/
|
|
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).
|
|
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.
|
|
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.
|
|
Ensure constants are used as hash keys and cleanup unused
constants. This gives a 10-15% improvement with
test/benchmark/request.rb
|
|
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.
|
|
|
|
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.
|
|
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.
|
|
The master _may_ run with different user/group/umask than the
workers. Since the logs were always created by the master
process, the master should rotate them first to ensure correct
ownership and permissions.
This way if the workers fail log rotation and die, they'll
be automatically respawned with the new logs in place.
|
|
|
|
Fix the logic in HttpParser up front so we don't have
to mess around with the following convoluted steps:
1. setting the HTTP_CONTENT_{LENGTH,TYPE} headers
2. reading the HTTP_CONTENT_{LENGTH,TYPE} headers again
3. setting the CONTENT_{LENGTH,TYPE} based on the
HTTP_-prefixed one
4. deleting the HTTP_CONTENT_{LENGTH,TYPE} headers
(since Rack doesn't like them)
1, 2, 3 were in the C code, 4 was in Ruby.
Now the logic is:
1. if CONTENT_{LENGTH,TYPE} headers are seen, don't prefix
with "HTTP_".
All the branch logic for the new code is done at init time, too
so there's no additional overhead in the HTTP parsing phase.
There's also no additional overhead of hash lookups in the extra
steps.
|
|
* Use waitpid2 to more reliably trap exit status
* Stop including Process namespace since it leads
to confusing conflicts.
|
|
This is a Rack handler that passes Rack::Lint running cgit
and so it has been lightly tested. No other CGI executables
have been run with it.
|
|
The body could be an IO object that is closeable.
So make sure we close it if it can be closed to
avoid file descriptor leakage.
|
|
This will only be enabled if we're daemonized and "real" WINCH
signals cannot be generated by resizing the terminal. This is
to avoid confusing developers who run in the foreground of a
terminal.
Additionally document procedures for reexecuting a running
binary.
|
|
This fixes a bug where listener names in the master process
would be incorrectly matched with the existing set; causing UNIX
sockets to be unbound and rebound; breaking things for child
processes.
This is a better fit anyways since it's higher level.
|
|
The daemonization logic between unicorn and unicorn_rails
scripts can definitely be shared.
Again: our daemonization logic is slightly non-standard since
our executables are designed to run in APP_ROOT/RAILS_ROOT and
not "/" like "normal" UNIX daemons.
|
|
|
|
|
|
Although I didn't like the idea initially, signal queueing
allows test_exec to run more reliably and the limited signal
queue size will prevent scary queued signal behavior.
Also, always wakeup the master immediately when CHLD is trapped
to reduce the performance impact of SIGHUP-based config
reloading. Combined with an extra check in test_exec, this
should make test_exec run much more reliably than before.
|
|
In nearly every app, if the current working directory
disappears, the app becomes broken, sometimes subtly. It can be
especially broken when preload_app is false (the default).
So just shut ourselves down to spare ourselves the
wasted CPU cycles on a dead app.
As a (hopefully) pleasant side effect, this allows
configurations with preload_app==false (the default) to do
application code reloads via SIGHUP (in addition to unicorn
config reloads).
|
|
This is to be consistent with the existing "pid"
and std{err,out}_path options which also take
paths relative to "~"
|
|
Or lack thereof on POSIX.
|
|
Just in case this stupid Ruby 1.9-ism creeps up on someone; I
haven't been able to reproduce I/O corruption from the test
cases, but better safe than sorry here.
|
|
|
|
|