Date | Commit message (Collapse) |
|
|
|
Thanks to Ben Sandofsky for the extra set of eyes
|
|
Under MRI 1.8, listen sockets do not appear to have the
nonblocking I/O flag on by default, nor does it set the
nonblocking I/O flag when calling #accept (but it does
when using #accept_nonblock, of course).
Normally this is not a problem even when using green threads
since MRI will internally select(2) on the file descriptor
before attempting a blocking (and immediately successful)
accept(2).
However, when sharing a listen descriptor across multiple
processes, spurious wakeups are likely to occur, causing
multiple processes may be woken up when a single client
connects.
This causes a problem because accept(2)-ing on multiple
threads/processes for a single connection causes blocking accepts in
multiple processes, leading to stalled green threads.
This is not an issue under 1.9 where a blocking accept() call
unlocks the GVL to let other threads run.
|
|
TeeInput may explicitly close on client disconnects to
avoid error messages being written to the socket, likewise
with "hack.io" users.
|
|
|
|
|
|
This exposes a client IO object directly to the underlying
application.
|
|
We now correctly exit!(2) if our master can't kill us.
|
|
Just die naturally here if threads don't die on
their own.
|
|
It's a tad faster for non-keepalive connections and should do
better on large SMP machines with many workers AND threads.
That means the ActorSpawn model in Rubinius is nothing more than
ThreadSpawn underneath (for now).
|
|
Make sure app errors get logged correctly, and we no longer
return a 500 response when a client EOFs the write end (but not
the read end) of a connection.
|
|
And change the default to 2 seconds, most clients can
render the page and load all URLs within 2 seconds.
|
|
If the Revactor implementation using lightweight Actors/Fibers
needs it, then thread implementations do, too.
|
|
Permissions for the logs could've been badly set by the master.
So we we'll let the master reopen them and refork children to
get around this problem. We have to be more careful when
reopening logs because we can reopen them in the middle of
client requests (we have to) whereas Unicorn has the luxury
of _knowing_ it has no active clients when it does the reopen.
|
|
Unicorn 0.94.0 got a more generic handle_error function
that's useful in the Thread* models. The Revactor one
is a little different but similar to be worth refactoring
to match our standard pieces.
|
|
It's already global...
|
|
It turns out neither the EventMachine and Rev classes
checked for master death in its heartbeat mechanism.
Since we managed to forget the same thing twice, we
now have a test case for it and also centralized the
code to remove duplication.
|
|
Array#count is not available until MRI 1.8.7
|
|
We use the "G" global constant from the Rev model everywhere
to simplify things a little.
Test cases are more consistent now, too.
|
|
Subtraction is a difficult concept for some folks (like
myself) to grasp and implement.
|
|
I need better tests for graceful shutdown...
|
|
Just like in Unicorn...
|
|
They were completely broken in the refactoring :x
|
|
The process-based heartbeat continues, but we no longer time
threads out just because a client is idle for any reason (for
now).
|
|
This can be common across everything
|
|
It'll be easier to maintain a common language for logging
and debugging.
|
|
Ensure we reset the per-thread time Thread.current[:t] with each
connection so we don't timeout long-lived connections.
|
|
This was breaking badly under 1.8 since Revactor couldn't be
included (the constant is listed once it is declared as an
autoload).
|
|
They're similar enough (especially as far as the constants go)
and allows a :Base to be used which basically acts like plain
Unicorn but with HTTP keepalive + pipelining support
|