about summary refs log tree commit homepage
path: root/lib/unicorn.rb
DateCommit message (Collapse)
2009-05-22Fix a warning about @pid being uninitialized
2009-05-22Ignore unhandled master signals in the workers
This makes it easier to use "killall -$SIGNAL unicorn" without having to lookup the correct PID.
2009-05-22Safer timeout handling and test case
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.
2009-04-25Fix log rotation being delayed in workers when idle
We were closing a no-longer-existent I/O object to break out of IO.select. This was broken in 0.6.0 but did not affect the worker when it was busy.
2009-04-24cleanup: avoid duped self-pipe init/replacement logic
We do this in both the worker and master processes, so avoid repeating ourselves.
2009-04-24SIGTT{IN,OU} {in,de}crements worker_processes
This allows dynamic tuning of the worker_processes count without having to restart existing ones. This also allows worker_processes to be set to a low initial amount in the config file for low-traffic deployments/upgrades and then scaled up as the old processes are killed off. Remove the proposed reexec_worker_processes from TODO since this is far more flexible and powerful. This will allow not-yet-existent third-party monitoring tools to dynamically change and scale worker processes according to site load without increasing the complexity of Unicorn itself.
2009-04-24Allow std{err,out}_path to be changed via HUP
Seems like a good idea to be able to relocate log files on a config reload.
2009-04-24minor cleanups and save a few variables
Saying to the world that I may have OCD...
2009-04-24Avoid getppid() if serving heavy traffic
As long as our speculative accept()s are succeeding, then avoid checking for master process death and keep processing requests. This allows us to save some syscalls under extremely heavy traffic spikes.
2009-04-24Fixup reference to a dead variable
Oops, this was broken in another yak-shaving commit: 9206bb5e54a0837e394e8b1c1a96e27ebaf44e77
2009-04-23Describe the global constants we use.
Avoid scaring the thread-safety-first crowd (as much :)
2009-04-23make SELF_PIPE is a global constant
Since it has to work inside signal handlers, there's no point in making it a per-object instance variable given the price of an instance variable in MRI...
2009-04-23Make LISTENERS and WORKERS global constants, too
Instance variables are expensive and we'd be encouraging something like a thread-safe mentality for using ivars when dealing with things that are global to the entire process.
2009-04-23IO_PURGATORY should be a global constant
Since file descriptors are only private to a process, do not treat them as Object-specific.
2009-04-21Cleanup some unnecessary requires
2009-04-21Remove @start_ctx instance variable
It's pointless to support multiple instances of it since this is per-process. However, the constant itself is now modifiable if anybody needs to tweak things for reexecution using a before_exec hook.
2009-04-21rename socket.rb => socket_helper.rb
We no longer have anything outside of SocketHelper module in that file, so just give it a more obvious name.
2009-04-16fix 100% CPU usage when idle
Oops, that was not just speculative accept(), but spammy accept()...
2009-04-15worker_loop cleanups, var golf, and yak-shaving
Ensure we always fchmod our tempfile in case of client error to avoid getting nuked in the next request cycle. Also, kill off some unnecessary variables since this method has too many variables anyways and we can overload the "nr" counter to do what "accepted" and "reopen_logs" did..
2009-04-15before_commit and before_exec can never be nil/false
So don't bother checking them again. Configurator already ensures that they're Proc objects for us, and we've been forgetting to check @before_fork since the beginning of time anyways... Consistency + less code = good
2009-04-14s/rotating/reopening/g in log messages
We don't (and won't ever) do log rotation within the process. That's the job of logrotate and tools like that. We just reopen logs like other reasonable daemons out there.
2009-04-14Explicitly trap SIGINT/SIGTERM again
Otherwise we get generally worthless backtraces and we don't want to clobber those for other signals, either.
2009-04-13Fix SIGINT/SIGTERM handling (broken in 0.5.0)
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.
2009-04-13Expose worker to {before,after}_fork hooks
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).
2009-04-13Remove unnecessary local variables in process_client
I'm golfing, really, but maybe we can be 0.00001% faster if we avoid naming some variables...
2009-04-13small cleanups in signal handling and worker init
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.
2009-04-12Don't bother restoring ENV or umask across reexec
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.
2009-04-12Remove unnecessary sync assignment
We never write to the file anyways, and fchmod is never buffered
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-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-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-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-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-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-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.