Date | Commit message (Collapse) |
|
|
|
By reraising SignalException in workers. Since we just rely on
default signal handlers for the majority of signals now, ensure
those signals actually exit the process.
|
|
|
|
I don't advocate running Unicorn on unprivileged ports anyways
since Unicorn should never be exposed directly to public
clients.
|
|
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).
|
|
I'm golfing, really, but maybe we can be 0.00001% faster
if we avoid naming some variables...
|
|
Since signals and signal handlers are process-wide, just make
SIG_QUEUE a global constant since there's absolutely no reason
it should be otherwise...
Restore default signal handlers when building app in case our
app does anything strange or gets hung, it's nice to know
SIG{INT,TERM} can be used to kill it while it's loading.
Additionally, there's little point in clearing arrays before
nilling them: just trust the GC to do its job properly.
|
|
Hopefully the world will just move to Rack faster
so we have less things to worry about.
|
|
If someone changes ENV or umask in the master process (via
before_fork or when loading the config), assume it was
intentional and just preserve it across reexec.
|
|
We never write to the file anyways, and fchmod is never buffered
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
* 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.
|
|
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.
|
|
Premade lambda/proc/Proc objects may all be passed, to the
hooks, not just anonymous blocks.
|
|
|
|
Just because I know regular expressions doesn't
mean I *have* to use them...
|
|
Multiple Unicorn applications one machine can get confusing
quickly. Regardless, make it easy to distinguish between
workers and the master process.
|
|
The newly open file descriptors live on as fd=1
and fd=2 anyways, so there's no reason to keep
duplicates around.
|
|
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.
|
|
Prevent subtle leaks here, too.
|
|
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.
|
|
|
|
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.
|