From b7a0074284d33352bb9e732c660b29162f34bf0e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 5 Jan 2011 23:05:05 -0800 Subject: close client socket after closing response body Response bodies may capture the block passed to each and save it for body.close, so don't close the socket before we have a chance to call body.close (cherry picked from commit b72a86f66c722d56a6d77ed1d2779ace6ad103ed) Conflicts: lib/unicorn/http_server.rb test/unit/test_response.rb --- lib/unicorn.rb | 1 + lib/unicorn/http_response.rb | 1 - t/t0018-write-on-close.sh | 23 +++++++++++++++++++++++ t/write-on-close.ru | 11 +++++++++++ test/unit/test_response.rb | 21 ++++++++++----------- 5 files changed, 45 insertions(+), 12 deletions(-) create mode 100755 t/t0018-write-on-close.sh create mode 100644 t/write-on-close.ru diff --git a/lib/unicorn.rb b/lib/unicorn.rb index 735354f..31332c9 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -646,6 +646,7 @@ module Unicorn response = app.call(env) end HttpResponse.write(client, response, HttpRequest::PARSER.headers?) + client.close # flushes and uncorks the socket immediately, no keepalive rescue => e handle_error(client, e) end diff --git a/lib/unicorn/http_response.rb b/lib/unicorn/http_response.rb index 6f1cd48..f3b5a82 100644 --- a/lib/unicorn/http_response.rb +++ b/lib/unicorn/http_response.rb @@ -63,7 +63,6 @@ module Unicorn::HttpResponse end body.each { |chunk| socket.write(chunk) } - socket.close # flushes and uncorks the socket immediately ensure body.respond_to?(:close) and body.close end diff --git a/t/t0018-write-on-close.sh b/t/t0018-write-on-close.sh new file mode 100755 index 0000000..3afefea --- /dev/null +++ b/t/t0018-write-on-close.sh @@ -0,0 +1,23 @@ +#!/bin/sh +. ./test-lib.sh +t_plan 4 "write-on-close tests for funky response-bodies" + +t_begin "setup and start" && { + unicorn_setup + unicorn -D -c $unicorn_config write-on-close.ru + unicorn_wait_start +} + +t_begin "write-on-close response body succeeds" && { + test xGoodbye = x"$(curl -sSf http://$listen/)" +} + +t_begin "killing succeeds" && { + kill $unicorn_pid +} + +t_begin "check stderr" && { + check_stderr +} + +t_done diff --git a/t/write-on-close.ru b/t/write-on-close.ru new file mode 100644 index 0000000..54a2f2e --- /dev/null +++ b/t/write-on-close.ru @@ -0,0 +1,11 @@ +class WriteOnClose + def each(&block) + @callback = block + end + + def close + @callback.call "7\r\nGoodbye\r\n0\r\n\r\n" + end +end +use Rack::ContentType, "text/plain" +run(lambda { |_| [ 200, [%w(Transfer-Encoding chunked)], WriteOnClose.new ] }) diff --git a/test/unit/test_response.rb b/test/unit/test_response.rb index f9eda8e..b3bc3a2 100644 --- a/test/unit/test_response.rb +++ b/test/unit/test_response.rb @@ -15,15 +15,14 @@ class ResponseTest < Test::Unit::TestCase def test_response_headers out = StringIO.new HttpResponse.write(out,[200, {"X-Whatever" => "stuff"}, ["cool"]]) - assert out.closed? - + assert ! out.closed? assert out.length > 0, "output didn't have data" end def test_response_string_status out = StringIO.new HttpResponse.write(out,['200', {}, []]) - assert out.closed? + assert ! out.closed? assert out.length > 0, "output didn't have data" assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/).size end @@ -33,7 +32,7 @@ class ResponseTest < Test::Unit::TestCase $, = "\f\v" out = StringIO.new HttpResponse.write(out,[200, {"X-k" => "cd","X-y" => "z"}, ["cool"]]) - assert out.closed? + assert ! out.closed? resp = out.string assert ! resp.include?("\f\v"), "output didn't use $, ($OFS)" ensure @@ -43,7 +42,7 @@ class ResponseTest < Test::Unit::TestCase def test_response_200 io = StringIO.new HttpResponse.write(io, [200, {}, []]) - assert io.closed? + assert ! io.closed? assert io.length > 0, "output didn't have data" end @@ -51,7 +50,7 @@ class ResponseTest < Test::Unit::TestCase code = 400 io = StringIO.new HttpResponse.write(io, [code, {}, []]) - assert io.closed? + assert ! io.closed? lines = io.string.split(/\r\n/) assert_match(/.* Bad Request$/, lines.first, "wrong default reason phrase") @@ -60,7 +59,7 @@ class ResponseTest < Test::Unit::TestCase def test_rack_multivalue_headers out = StringIO.new HttpResponse.write(out,[200, {"X-Whatever" => "stuff\nbleh"}, []]) - assert out.closed? + assert ! out.closed? assert_match(/^X-Whatever: stuff\r\nX-Whatever: bleh\r\n/, out.string) end @@ -69,7 +68,7 @@ class ResponseTest < Test::Unit::TestCase def test_status_header_added out = StringIO.new HttpResponse.write(out,[200, {"X-Whatever" => "stuff"}, []]) - assert out.closed? + assert ! out.closed? assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size end @@ -80,7 +79,7 @@ class ResponseTest < Test::Unit::TestCase out = StringIO.new header_hash = {"X-Whatever" => "stuff", 'StaTus' => "666" } HttpResponse.write(out,[200, header_hash, []]) - assert out.closed? + assert ! out.closed? assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size assert_equal 1, out.string.split(/\r\n/).grep(/^Status:/i).size end @@ -91,7 +90,7 @@ class ResponseTest < Test::Unit::TestCase body.rewind out = StringIO.new HttpResponse.write(out,[200, {}, body]) - assert out.closed? + assert ! out.closed? assert body.closed? assert_match(expect_body, out.string.split(/\r\n/).last) end @@ -99,7 +98,7 @@ class ResponseTest < Test::Unit::TestCase def test_unknown_status_pass_through out = StringIO.new HttpResponse.write(out,["666 I AM THE BEAST", {}, [] ]) - assert out.closed? + assert ! out.closed? headers = out.string.split(/\r\n\r\n/).first.split(/\r\n/) assert %r{\AHTTP/\d\.\d 666 I AM THE BEAST\z}.match(headers[0]) status = headers.grep(/\AStatus:/i).first -- cgit v1.2.3-24-ge0c7 From 3587edb6e88ebe5c24cdde090ba8dd98de493d63 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 6 Jan 2011 15:40:54 -0800 Subject: unicorn 1.1.6 - one minor, esoteric bugfix We now close the client socket after closing the response body. This does not affect most applications that run under Unicorn, in fact, it may not affect any. --- GIT-VERSION-GEN | 2 +- lib/unicorn/const.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 9e60ee9..d182227 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.1.5.GIT +DEF_VER=v1.1.6.GIT LF=' ' diff --git a/lib/unicorn/const.rb b/lib/unicorn/const.rb index 2f0b106..1c56809 100644 --- a/lib/unicorn/const.rb +++ b/lib/unicorn/const.rb @@ -8,8 +8,8 @@ module Unicorn # Symbols did not really improve things much compared to constants. module Const - # The current version of Unicorn, currently 1.1.5 - UNICORN_VERSION="1.1.5" + # The current version of Unicorn, currently 1.1.6 + UNICORN_VERSION="1.1.6" DEFAULT_HOST = "0.0.0.0" # default TCP listen host address DEFAULT_PORT = 8080 # default TCP listen port -- cgit v1.2.3-24-ge0c7 From d385bc4f3ed7b783b7414f5d34299bd2bf242fe6 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 21 Jan 2011 04:01:01 +0000 Subject: exec_cgi: handle Status header in CGI response We no longer blindly return 200 if the CGI returned another error code. We also don't want two Status headers in our output since we no longer filter it out. (cherry picked from commit 6cca8e61c66c1c2a8ebe260813fa83e44530a768) --- lib/unicorn/app/exec_cgi.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/unicorn/app/exec_cgi.rb b/lib/unicorn/app/exec_cgi.rb index 412c1d9..ff5f53a 100644 --- a/lib/unicorn/app/exec_cgi.rb +++ b/lib/unicorn/app/exec_cgi.rb @@ -113,8 +113,9 @@ module Unicorn::App when /^[ \t]/ then headers[prev] << "\n#{line}" if prev end end + status = headers.delete("Status") || 200 headers['Content-Length'] = size.to_s - [ 200, headers, out ] + [ status, headers, out ] end # ensures rack.input is a file handle that we can redirect stdin to -- cgit v1.2.3-24-ge0c7 From fe0dd93cd9cb97b46f6cfb4b1e370e38717a93f0 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 29 Apr 2011 15:48:35 -0700 Subject: oob_gc: reimplement to fix breakage and add tests This was broken since v3.3.1[1] and v1.1.6[2] since nginx relies on a closed socket (and not Content-Length/Transfer-Encoding) to detect a response completion. We have to close the client socket before invoking GC to ensure the client sees the response in a timely manner. [1] - commit b72a86f66c722d56a6d77ed1d2779ace6ad103ed [2] - commit b7a0074284d33352bb9e732c660b29162f34bf0e (cherry picked from commit faeb3223636c39ea8df4017dc9a9d39ac649b26d) Conflicts: examples/big_app_gc.rb lib/unicorn/oob_gc.rb --- examples/big_app_gc.rb | 35 +--------------- lib/unicorn/oob_gc.rb | 111 +++++++++++++++++++++++++++---------------------- t/oob_gc.ru | 21 ++++++++++ t/oob_gc_path.ru | 21 ++++++++++ t/t9001-oob_gc.sh | 47 +++++++++++++++++++++ t/t9002-oob_gc-path.sh | 75 +++++++++++++++++++++++++++++++++ 6 files changed, 227 insertions(+), 83 deletions(-) create mode 100644 t/oob_gc.ru create mode 100644 t/oob_gc_path.ru create mode 100755 t/t9001-oob_gc.sh create mode 100644 t/t9002-oob_gc-path.sh diff --git a/examples/big_app_gc.rb b/examples/big_app_gc.rb index 779c3ee..c4c8b04 100644 --- a/examples/big_app_gc.rb +++ b/examples/big_app_gc.rb @@ -1,33 +1,2 @@ -# Run GC after every request, before attempting to accept more connections. -# -# You could customize this patch to read REQ["PATH_INFO"] and only -# call GC.start after expensive requests. -# -# We could have this wrap the response body.close as middleware, but the -# scannable stack is would still be bigger than it would be here. -# -# This shouldn't hurt overall performance as long as the server cluster -# is at <=50% CPU capacity, and improves the performance of most memory -# intensive requests. This serves to improve _client-visible_ -# performance (possibly at the cost of overall performance). -# -# We'll call GC after each request is been written out to the socket, so -# the client never sees the extra GC hit it. It's ideal to call the GC -# inside the HTTP server (vs middleware or hooks) since the stack is -# smaller at this point, so the GC will both be faster and more -# effective at releasing unused memory. -# -# This monkey patch is _only_ effective for applications that use a lot -# of memory, and will hurt simpler apps/endpoints that can process -# multiple requests before incurring GC. - -class Unicorn::HttpServer - REQ = Unicorn::HttpRequest::REQ - alias _process_client process_client - undef_method :process_client - def process_client(client) - _process_client(client) - REQ.clear - GC.start - end -end if defined?(Unicorn) +# see {Unicorn::OobGC}[http://unicorn.bogomips.org/Unicorn/OobGC.html] +# Unicorn::OobGC was broken in Unicorn v3.3.1 - v3.6.1 and fixed in v3.6.2 diff --git a/lib/unicorn/oob_gc.rb b/lib/unicorn/oob_gc.rb index 8dc4dcf..a0e8f1d 100644 --- a/lib/unicorn/oob_gc.rb +++ b/lib/unicorn/oob_gc.rb @@ -1,58 +1,69 @@ # -*- encoding: binary -*- -module Unicorn - # Run GC after every request, after closing the client socket and - # before attempting to accept more connections. - # - # This shouldn't hurt overall performance as long as the server cluster - # is at <50% CPU capacity, and improves the performance of most memory - # intensive requests. This serves to improve _client-visible_ - # performance (possibly at the cost of overall performance). - # - # We'll call GC after each request is been written out to the socket, so - # the client never sees the extra GC hit it. - # - # This middleware is _only_ effective for applications that use a lot - # of memory, and will hurt simpler apps/endpoints that can process - # multiple requests before incurring GC. - # - # This middleware is only designed to work with Unicorn, as it harms - # keepalive performance. - # - # Example (in config.ru): - # - # require 'unicorn/oob_gc' - # - # # GC ever two requests that hit /expensive/foo or /more_expensive/foo - # # in your app. By default, this will GC once every 5 requests - # # for all endpoints in your app - # use Unicorn::OobGC, 2, %r{\A/(?:expensive/foo|more_expensive/foo)} - class OobGC < Struct.new(:app, :interval, :path, :nr, :env, :body) - - def initialize(app, interval = 5, path = %r{\A/}) - super(app, interval, path, interval) - end - - def call(env) - status, headers, self.body = app.call(self.env = env) - [ status, headers, self ] - end +# Runs GC after requests, after closing the client socket and +# before attempting to accept more connections. +# +# This shouldn't hurt overall performance as long as the server cluster +# is at <50% CPU capacity, and improves the performance of most memory +# intensive requests. This serves to improve _client-visible_ +# performance (possibly at the cost of overall performance). +# +# Increasing the number of +worker_processes+ may be necessary to +# improve average client response times because some of your workers +# will be busy doing GC and unable to service clients. Think of +# using more workers with this module as a poor man's concurrent GC. +# +# We'll call GC after each request is been written out to the socket, so +# the client never sees the extra GC hit it. +# +# This middleware is _only_ effective for applications that use a lot +# of memory, and will hurt simpler apps/endpoints that can process +# multiple requests before incurring GC. +# +# This middleware is only designed to work with unicorn, as it harms +# performance with keepalive-enabled servers. +# +# Example (in config.ru): +# +# require 'unicorn/oob_gc' +# +# # GC ever two requests that hit /expensive/foo or /more_expensive/foo +# # in your app. By default, this will GC once every 5 requests +# # for all endpoints in your app +# use Unicorn::OobGC, 2, %r{\A/(?:expensive/foo|more_expensive/foo)} +# +# Feedback from users of early implementations of this module: +# * http://comments.gmane.org/gmane.comp.lang.ruby.unicorn.general/486 +# * http://article.gmane.org/gmane.comp.lang.ruby.unicorn.general/596 +module Unicorn::OobGC - def each(&block) - body.each(&block) + # this pretends to be Rack middleware because it used to be + # But we need to hook into unicorn internals so we need to close + # the socket before clearing the request env. + # + # +interval+ is the number of requests matching the +path+ regular + # expression before invoking GC. + def self.new(app, interval = 5, path = %r{\A/}) + @@nr = interval + self.const_set :OOBGC_PATH, path + self.const_set :OOBGC_INTERVAL, interval + self.const_set :OOBGC_ENV, Unicorn::HttpRequest::REQ + ObjectSpace.each_object(Unicorn::HttpServer) do |s| + s.extend(self) end + app # pretend to be Rack middleware since it was in the past + end - # in Unicorn, this is closed _after_ the client socket - def close - body.close if body.respond_to?(:close) - - if path =~ env['PATH_INFO'] && ((self.nr -= 1) <= 0) - self.nr = interval - self.body = nil - env.clear - GC.start - end + #:stopdoc: + PATH_INFO = "PATH_INFO" + def process_client(client) + super(client) # Unicorn::HttpServer#process_client + if OOBGC_PATH =~ OOBGC_ENV[PATH_INFO] && ((@@nr -= 1) <= 0) + @@nr = OOBGC_INTERVAL + OOBGC_ENV.clear + GC.start end - end + + # :startdoc: end diff --git a/t/oob_gc.ru b/t/oob_gc.ru new file mode 100644 index 0000000..c6035b6 --- /dev/null +++ b/t/oob_gc.ru @@ -0,0 +1,21 @@ +#\-E none +require 'unicorn/oob_gc' +use Rack::ContentLength +use Rack::ContentType, "text/plain" +use Unicorn::OobGC +$gc_started = false + +# Mock GC.start +def GC.start + ObjectSpace.each_object(BasicSocket) do |x| + next if Unicorn::HttpServer::LISTENERS.include?(x) + x.closed? or abort "not closed #{x}" + end + $gc_started = true +end +run lambda { |env| + if "/gc_reset" == env["PATH_INFO"] && "POST" == env["REQUEST_METHOD"] + $gc_started = false + end + [ 200, {}, [ "#$gc_started\n" ] ] +} diff --git a/t/oob_gc_path.ru b/t/oob_gc_path.ru new file mode 100644 index 0000000..e936a85 --- /dev/null +++ b/t/oob_gc_path.ru @@ -0,0 +1,21 @@ +#\-E none +require 'unicorn/oob_gc' +use Rack::ContentLength +use Rack::ContentType, "text/plain" +use Unicorn::OobGC, 5, /BAD/ +$gc_started = false + +# Mock GC.start +def GC.start + ObjectSpace.each_object(BasicSocket) do |x| + next if Unicorn::HttpServer::LISTENERS.include?(x) + x.closed? or abort "not closed #{x}" + end + $gc_started = true +end +run lambda { |env| + if "/gc_reset" == env["PATH_INFO"] && "POST" == env["REQUEST_METHOD"] + $gc_started = false + end + [ 200, {}, [ "#$gc_started\n" ] ] +} diff --git a/t/t9001-oob_gc.sh b/t/t9001-oob_gc.sh new file mode 100755 index 0000000..dcd8100 --- /dev/null +++ b/t/t9001-oob_gc.sh @@ -0,0 +1,47 @@ +#!/bin/sh +. ./test-lib.sh +t_plan 9 "OobGC test" + +t_begin "setup and start" && { + unicorn_setup + unicorn -D -c $unicorn_config oob_gc.ru + unicorn_wait_start +} + +t_begin "test default interval (4 requests)" && { + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) +} + +t_begin "GC starting-request returns immediately" && { + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) +} + +t_begin "GC is started after 5 requests" && { + test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp) +} + +t_begin "reset GC" && { + test xfalse = x$(curl -vsSf -X POST http://$listen/gc_reset 2>> $tmp) +} + +t_begin "test default interval again (3 requests)" && { + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) +} + +t_begin "GC is started after 5 requests" && { + test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp) +} + +t_begin "killing succeeds" && { + kill -QUIT $unicorn_pid +} + +t_begin "check_stderr" && check_stderr +dbgcat r_err + +t_done diff --git a/t/t9002-oob_gc-path.sh b/t/t9002-oob_gc-path.sh new file mode 100644 index 0000000..d4e795b --- /dev/null +++ b/t/t9002-oob_gc-path.sh @@ -0,0 +1,75 @@ +#!/bin/sh +. ./test-lib.sh +t_plan 12 "OobGC test with limited path" + +t_begin "setup and start" && { + unicorn_setup + unicorn -D -c $unicorn_config oob_gc_path.ru + unicorn_wait_start +} + +t_begin "test default is noop" && { + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) +} + +t_begin "4 bad requests to bump counter" && { + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) +} + +t_begin "GC-starting request returns immediately" && { + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) +} + +t_begin "GC was started after 5 requests" && { + test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp) +} + +t_begin "reset GC" && { + test xfalse = x$(curl -vsSf -X POST http://$listen/gc_reset 2>> $tmp) +} + +t_begin "test default is noop" && { + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp) +} + +t_begin "4 bad requests to bump counter" && { + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) +} + +t_begin "GC-starting request returns immediately" && { + test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp) +} + +t_begin "GC was started after 5 requests" && { + test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp) +} + +t_begin "killing succeeds" && { + kill -QUIT $unicorn_pid +} + +t_begin "check_stderr" && check_stderr + +t_done -- cgit v1.2.3-24-ge0c7 From 0874125ce56d52cee0f634712e69d1387eadfae1 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 30 Apr 2011 04:56:28 +0000 Subject: unicorn 1.1.7 - major fixes to minor components No changes to the core code, so this release only affects users of the Unicorn::OobGC and Unicorn::ExecCGI modules. Unicorn::OobGC was totally broken by the fix in the v1.1.6 release and is now reimplemented. Unicorn::ExecCGI (which hardly anybody uses) now returns proper HTTP status codes. --- GIT-VERSION-GEN | 2 +- lib/unicorn/const.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index d182227..7a97c16 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.1.6.GIT +DEF_VER=v1.1.7.GIT LF=' ' diff --git a/lib/unicorn/const.rb b/lib/unicorn/const.rb index 1c56809..b428be5 100644 --- a/lib/unicorn/const.rb +++ b/lib/unicorn/const.rb @@ -8,8 +8,8 @@ module Unicorn # Symbols did not really improve things much compared to constants. module Const - # The current version of Unicorn, currently 1.1.6 - UNICORN_VERSION="1.1.6" + # The current version of Unicorn, currently 1.1.7 + UNICORN_VERSION="1.1.7" DEFAULT_HOST = "0.0.0.0" # default TCP listen host address DEFAULT_PORT = 8080 # default TCP listen port -- cgit v1.2.3-24-ge0c7