From 101fb9ad1372e97ddf998c7fd677e352719c90e8 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 9 Feb 2009 14:26:34 -0800 Subject: Refactor and get exec + FD inheritance working Along with worker process management. This is nginx-style inplace upgrading (I don't know of another web server that does this). Basically we can preserve our opened listen sockets across entire executable upgrades. Signals: USR2 - Sending USR2 to the master unicorn process will cause it to exec a new master and keep the original workers running. This is useful to validate that the new code changes took place are valid and don't immediately die. Once the changes are validated (manually), you may send QUIT to the original master process to have it gracefully exit. HUP - Sending this to the master will make it immediately exec a new binary and cause the old workers to gracefully exit. Use this if you're certain the latest changes to Unicorn (and your app) are ready and don't need validating. Unlike nginx, re-execing a new binary will pick up any and all configuration changes. However listener sockets cannot be removed when exec-ing; only added (for now). I apologize for making such a big change in one commit, but once I got the ability to replace the entire codebase while preserving connections, it was too tempting to continue working. So I wrote a large chunk of this while hitting the unicorn-hello-world app with the following loop: while curl -vSsfN http://0:8080; do date +%N; done _Zero_ requests lost across multiple restarts. --- lib/unicorn/http_request.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'lib/unicorn/http_request.rb') diff --git a/lib/unicorn/http_request.rb b/lib/unicorn/http_request.rb index 0a8c5b1..47600d6 100644 --- a/lib/unicorn/http_request.rb +++ b/lib/unicorn/http_request.rb @@ -1,3 +1,9 @@ +require 'tempfile' +require 'uri' +require 'stringio' + +# compiled extension +require 'http11' module Unicorn # @@ -54,7 +60,7 @@ module Unicorn # identify the client for the immediate request to the server; # that client may be a proxy, gateway, or other intermediary # acting on behalf of the actual source client." - @params[Const::REMOTE_ADDR] = socket.unicorn_peeraddr.last + @params[Const::REMOTE_ADDR] = socket.unicorn_peeraddr handle_body(socket) and return rack_env # success! return nil # fail @@ -72,10 +78,10 @@ module Unicorn rescue HttpParserError => e @logger.error "HTTP parse error, malformed request " \ "(#{@params[Const::HTTP_X_FORWARDED_FOR] || - socket.unicorn_peeraddr.last}): #{e.inspect}" + socket.unicorn_peeraddr}): #{e.inspect}" @logger.error "REQUEST DATA: #{data.inspect}\n---\n" \ "PARAMS: #{@params.inspect}\n---\n" - socket.close rescue nil + socket.closed? or socket.close rescue nil nil end @@ -152,7 +158,7 @@ module Unicorn true # success! rescue Object => e logger.error "Error reading HTTP body: #{e.inspect}" - socket.close rescue nil + socket.closed? or socket.close rescue nil # Any errors means we should delete the file, including if the file # is dumped. Truncate it ASAP to help avoid page flushes to disk. -- cgit v1.2.3-24-ge0c7