Date | Commit message (Collapse) |
|
test/test_helper doesn't seem to be required correctly anymore,
since we know our own module/test names don't conflict, just
fix RUBYLIB to include $(test_prefix)
With test_util.rb, using #reopen with Tempfile objects seems
prone to the objects being closed. Not completely sure what is
going on but I'll just sidestep around it since I've stopped
trusting Tempfile by now...
(cherry picked from commit 344b85ff28e160daa6563ab7c80b733abdeb874a)
|
|
Must have multiple headers to test this effectively
|
|
Rack::Lint says they just have to work when to_i is
called on the status, so that's what we'll do.
|
|
2 seconds is still prone to race conditions under high load.
We're intentionally less accurate than we could be in order to
reduce syscall and method dispatch overhead.
|
|
Ensure we preserve both internal and external encodings
when reopening logs.
|
|
These potentially leaves an open file handle around until the
next request hits the process, but this makes the common case
faster.
|
|
Otherwise there's a chance a child won't have a socket bound by
the time we're trying to connect.
|
|
Use SIGQUIT if you're going to be nice and do graceful
shutdowns. Sometimes people run real applications on this
server and SIGINT/SIGTERM get lost/trapped when Object is
rescued and that is not good. Also make sure we break out of
the loop properly when the master is dead.
Testcases added for both SIGINT and dead master handling.
|
|
Timeouts of less than 2 seconds are unsafe due to the lack of
subsecond resolution in most POSIX filesystems. This is the
trade-off for using a low-complexity solution for timeouts.
Since this type of timeout is a last resort; 2 seconds is not
entirely unreasonable IMNSHO. Additionally, timing out too
aggressively can put us in a fork loop and slow down the system.
Of course, the default is 60 seconds and most people do not
bother to change it.
|
|
readpartial is actually as low-level as sysread is,
except it's less likely to throw exceptions and
won't change the blocking/non-blocking status of
a file descriptor (we explicitly enable blocking I/O)
|
|
It seems most applications use buffered IO#read instead of
IO#sysread. So make sure our encoding is set correctly for
buffered IO#read applications, too.
|
|
|
|
The following specifications to bind port 8080 on all interfaces
are now accepted in the configuration file:
listen "8080" # (with quotes)
listen 8080 # (without quotes)
|
|
Avoid creating garbage every time we lookup the status code
along with the message. Also, we can use global const arrays
for a little extra performance because we only write one-at-a
time
Looking at MRI 1.8, Array#join with an empty string argument is
slightly better because it skips an append for every iteration.
|
|
Otherwise the GC will unlink sockets. A better
solution (purgatory?) may be needed...
|
|
StringIO.new(partial_body) does not update the offset for new
writes. So instead create the StringIO object and then syswrite
to it and try to follow the same code path used by large uploads
which use Tempfiles.
|
|
|
|
They aren't common, but apparently there exist
URLs with them, so we'll support them.
|
|
This removes the #unicorn_peeraddr methods from TCPSocket and
UNIXSocket core classes. Instead, just move that logic into the
only place it needs to be used in HttpRequest.
|
|
We now parse the scheme, host and port from Absolute URIs and
ignore them if the equivalents are specified in the other
headers.
|
|
This means "Host: foo-bar:" (trailing colon) will assume
server_port is 80, not a blank string.
|
|
|
|
It's part of the HTTP/1.1 (rfc2616), so we might as well
handle it in there and set PATH_INFO while we're at it.
Also, make "OPTIONS *" test not fail Rack::Lint
|
|
Sockets always return binary encoded data, so when
StringIO.new(string) is called, that StringIO object inherits
the encoding of the initial string it was created with.
And yes, Ruby 1.9 still makes me seriously uncomfortable with
I/O manipulation since the encoding layer does things behind my
back. UNIX is (and should always be) just a bag of bytes!
Signed-off-by: Eric Wong <normalperson@yhbt.net>
|
|
Avoid creating new string objects and then discarding them right
away by stuffing non-constant but always-present headers into
the initial output.
|
|
There are weird (and possibly broken) clients out there that
require it despite being present in the first line of the
response. So be nice and accomodate them. Keep in mind that
the Rack SPEC explicitly forbids this header from being in the
headers returned by the Rack-based application; so we have to
always inject it ourselves and ignore it if the application
sets it.
|
|
Instead of just worker.nr. This is a configuration file/API
change and will break existing configurations.
This allows worker.tempfile to be exposed to the hooks
so ownership changes can still happen on it.
On the other hand, I don't know of many people actually
using this feature (or Unicorn).
|
|
This was back when I did s/mongrel/Unicorn/g
on the sources.
|
|
Avoid using strcmp() since it could break badly if
Ruby ever stopped null-terminating strings C-style.
We're also freezing "http" as a global. Rack does not
explicitly permit nor deny this, and Mongrel has always
used frozen strings as hash values in other places.
|
|
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.
|
|
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.
|
|
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.
|
|
* Test for '*' in "OPTIONS * HTTP/1.1" for now (even though
Rack doesn't like it).
* Some clients can send absolute URIs, too
|
|
Run tests with warnings so we detect stupid things like this.
|
|
|
|
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.
|
|
I/O on slow descriptors can be interrupted so make sure we
(and Ruby itself) are handling EINTR correctly.
|
|
Premade lambda/proc/Proc objects may all be passed, to the
hooks, not just anonymous blocks.
|
|
We need to ensure the next request has started
processing before we can guarantee a temp file
has been unlinked.
|
|
* 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.
|
|
"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.
|
|
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 is in the Rack specification and a good idea. Remind
ourselves to prevent file descriptor or other resource leaks in
case the body is not an Array.
|
|
We always close the socket immediately after a
successful write for two reasons:
1) To prevent error responses from being rewritten.
If we throw an exception in our request/app/response
chain, we'll attempt to write an HTTP 400/500 response
out if the socket is open. No way to write to
an open socket.
2) To uncork the socket if TCP_CORK is enabled (Linux)
ASAP. This should be a tick faster than waiting
to go back up the stack and close it there.
|
|
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.
|
|
|
|
* 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!
|
|
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/
|