unicorn 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document CHANGED
@@ -1,4 +1,5 @@
1
1
  README
2
+ TUNING
2
3
  PHILOSOPHY
3
4
  DESIGN
4
5
  CONTRIBUTORS
data/CHANGELOG CHANGED
@@ -1,3 +1,4 @@
1
+ v0.7.1 - minor fixes, cleanups and documentation improvements
1
2
  v0.7.0 - rack.version is 1.0
2
3
  v0.6.0 - cleanups + optimizations, signals to {in,de}crement processes
3
4
  v0.5.4 - fix data corruption with some small uploads (not curl)
@@ -53,8 +53,10 @@ $(test_prefix)/.stamp: $(inst_deps)
53
53
  $(MAKE) -C $(test_prefix) http11 shebang
54
54
  > $@
55
55
 
56
+ bins := $(wildcard bin/*)
57
+
56
58
  # this is only intended to be run within $(test_prefix)
57
- shebang: bin/unicorn bin/unicorn_rails
59
+ shebang: $(bins)
58
60
  $(ruby) -i -p -e '$$_.gsub!(%r{^#!.*$$},"#!$(ruby_bin)")' $^
59
61
 
60
62
  t_log := $(T_log) $(T_n_log)
@@ -97,7 +99,7 @@ $(T): export RUBYLIB := $(test_prefix)/lib:$(RUBYLIB)
97
99
  $(T): $(test_prefix)/.stamp
98
100
  $(run_test)
99
101
 
100
- install: bin/unicorn bin/unicorn_rails
102
+ install: $(bins)
101
103
  $(prep_setup_rb)
102
104
  $(RM) -r .install-tmp
103
105
  mkdir .install-tmp
data/Manifest CHANGED
@@ -11,8 +11,10 @@ README
11
11
  Rakefile
12
12
  SIGNALS
13
13
  TODO
14
+ TUNING
14
15
  bin/unicorn
15
16
  bin/unicorn_rails
17
+ examples/init.sh
16
18
  ext/unicorn/http11/ext_help.h
17
19
  ext/unicorn/http11/extconf.rb
18
20
  ext/unicorn/http11/http11.c
@@ -127,3 +129,4 @@ test/unit/test_server.rb
127
129
  test/unit/test_signals.rb
128
130
  test/unit/test_socket_helper.rb
129
131
  test/unit/test_upload.rb
132
+ test/unit/test_util.rb
data/README CHANGED
@@ -103,7 +103,7 @@ In RAILS_ROOT, run:
103
103
  unicorn_rails
104
104
 
105
105
  Unicorn will bind to all interfaces TCP port 8080 by default.
106
- You may use the '-l/--listen' switch to bind to a different
106
+ You may use the +-l/--listen+ switch to bind to a different
107
107
  address:port or a UNIX socket.
108
108
 
109
109
  === Configuration File(s)
@@ -111,7 +111,7 @@ address:port or a UNIX socket.
111
111
  Unicorn will look for the config.ru file used by rackup in APP_ROOT.
112
112
 
113
113
  For deployments, it can use a config file for Unicorn-specific options
114
- specified by the --config-file/-c command-line switch. See
114
+ specified by the +--config-file/-c+ command-line switch. See
115
115
  Unicorn::Configurator for the syntax of the Unicorn-specific options.
116
116
  The default settings are designed for maximum out-of-the-box
117
117
  compatibility with existing applications.
data/TODO CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  * integration tests with nginx including bad client handling
4
4
 
5
- * tests for timeout
6
-
7
5
  * manpages (why do so few Ruby executables come with proper manpages?)
8
6
 
9
7
  == 1.1.0
data/TUNING ADDED
@@ -0,0 +1,63 @@
1
+ = Tuning Unicorn
2
+
3
+ Unicorn performance is generally as good as a (mostly) Ruby web server
4
+ can provide. Most often the performance bottleneck is in the web
5
+ application running on Unicorn rather than Unicorn itself.
6
+
7
+ == Unicorn Configuration
8
+
9
+ See Unicorn::Configurator for details on the config file format.
10
+
11
+ * Setting a very low value for the :backlog parameter in "listen"
12
+ directives can allow failover to happen more quickly if your
13
+ cluster is configured for it.
14
+
15
+ * :rcvbuf and :sndbuf parameters generally do not need to be set for TCP
16
+ listeners under Linux 2.6 because auto-tuning is enabled. UNIX domain
17
+ sockets do not have auto-tuning buffer sizes; so increasing those will
18
+ allow syscalls and task switches to be saved for larger requests
19
+ and responses.
20
+
21
+ * Setting "preload_app true" can allow copy-on-write-friendly GC to
22
+ be used to save memory. It will probably not work out of the box with
23
+ applications that open sockets or perform random I/O on files.
24
+ Databases like TokyoCabinet use concurrency-safe pread()/pwrite()
25
+ functions for safe sharing of database file descriptors across
26
+ processes.
27
+
28
+ * On POSIX-compliant filesystems, it is safe for multiple threads or
29
+ processes to append to one log file as long as all the processes are
30
+ have them unbuffered (File#sync = true) or they are
31
+ record(line)-buffered in userspace.
32
+
33
+ * worker_processes should be scaled to the number of processes your
34
+ backend system(s) can support. DO NOT scale it to the number of
35
+ external network clients your application expects to be serving.
36
+ Unicorn is NOT for serving slow clients, that is the job of nginx.
37
+
38
+ == Kernel Parameters (Linux sysctl)
39
+
40
+ WARNING: Do not change system parameters unless you know what you're doing!
41
+
42
+ * net.core.rmem_max and net.core.wmem_max can increase the allowed
43
+ size of :rcvbuf and :sndbuf respectively. This is mostly only useful
44
+ for UNIX domain sockets which do not have auto-tuning buffer sizes.
45
+
46
+ * For load testing/benchmarking with UNIX domain sockets, you should
47
+ consider increasing net.core.somaxconn or else nginx will start
48
+ failing to connect under heavy load.
49
+
50
+ * If you're running out of local ports, consider lowering
51
+ net.ipv4.tcp_fin_timeout to 20-30 (default: 60 seconds). Also
52
+ consider widening the usable port range by changing
53
+ net.ipv4.ip_local_port_range.
54
+
55
+ * Setting net.ipv4.tcp_timestamps=1 will also allow setting
56
+ net.ipv4.tcp_tw_reuse=1 and net.ipv4.tcp_tw_recycle=1, which along
57
+ with the above settings can slow down port exhaustion. Not all
58
+ networks are compatible with these settings, check with your friendly
59
+ network administrator before changing these.
60
+
61
+ * Increasing the MTU size can reduce framing overhead for larger
62
+ transfers. One often-overlooked detail is that the loopback
63
+ device (usually "lo") can have its MTU increased, too.
@@ -0,0 +1,54 @@
1
+ #!/bin/sh
2
+ set -u
3
+ set -e
4
+ # Example init script, this can be used with nginx, too,
5
+ # since nginx and unicorn accept the same signals
6
+
7
+ # Feel free to change any of the following variables for your app:
8
+ APP_ROOT=/home/x/my_app/current
9
+ PID=$APP_ROOT/tmp/pids/unicorn.pid
10
+ CMD="/usr/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb"
11
+ INIT_CONF=$APP_ROOT/config/init.conf
12
+
13
+ test -f "$INIT_CONF" && . $INIT_CONF
14
+
15
+ old_pid="$PID.oldbin"
16
+
17
+ cd $APP_ROOT || exit 1
18
+
19
+ sig () {
20
+ test -s "$PID" && kill -$1 `cat $PID`
21
+ }
22
+
23
+ oldsig () {
24
+ test -s $old_pid && kill -$1 `cat $old_pid`
25
+ }
26
+
27
+ case $1 in
28
+ start)
29
+ sig 0 && echo >&2 "Already running" && exit 0
30
+ $CMD
31
+ ;;
32
+ stop)
33
+ sig QUIT && exit 0
34
+ echo >&2 "Not running"
35
+ ;;
36
+ force-stop)
37
+ sig TERM && exit 0
38
+ echo >&2 "Not running"
39
+ ;;
40
+ restart|reload)
41
+ sig HUP && echo reloaded OK && exit 0
42
+ echo >&2 "Couldn't reload, starting '$CMD' instead"
43
+ $CMD
44
+ ;;
45
+ upgrade)
46
+ sig USR2 && sleep 2 && sig 0 && oldsig QUIT && exit 0
47
+ echo >&2 "Couldn't upgrade, starting '$CMD' instead"
48
+ $CMD
49
+ ;;
50
+ *)
51
+ echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop>"
52
+ exit 1
53
+ ;;
54
+ esac
@@ -64,6 +64,7 @@ module Unicorn
64
64
  # incoming requests on the socket.
65
65
  def initialize(app, options = {})
66
66
  @app = app
67
+ @pid = nil
67
68
  @reexec_pid = 0
68
69
  @init_listeners = options[:listeners] ? options[:listeners].dup : []
69
70
  @config = Configurator.new(options.merge(:use_defaults => true))
@@ -375,9 +376,8 @@ module Unicorn
375
376
  # is stale for >@timeout seconds, then we'll kill the corresponding
376
377
  # worker.
377
378
  def murder_lazy_workers
378
- now = Time.now
379
379
  WORKERS.each_pair do |pid, worker|
380
- (now - worker.tempfile.ctime) <= @timeout and next
380
+ Time.now - worker.tempfile.ctime <= @timeout and next
381
381
  logger.error "worker=#{worker.nr} PID:#{pid} is too old, killing"
382
382
  kill_worker(:KILL, pid) # take no prisoners for @timeout violations
383
383
  worker.tempfile.close rescue nil
@@ -444,7 +444,7 @@ module Unicorn
444
444
  # traps for USR1, USR2, and HUP may be set in the @after_fork Proc
445
445
  # by the user.
446
446
  def init_worker_process(worker)
447
- QUEUE_SIGS.each { |sig| trap(sig, 'DEFAULT') }
447
+ QUEUE_SIGS.each { |sig| trap(sig, 'IGNORE') }
448
448
  trap(:CHLD, 'DEFAULT')
449
449
  SIG_QUEUE.clear
450
450
  proc_name "worker[#{worker.nr}]"
@@ -69,9 +69,9 @@ module Unicorn::App
69
69
  ENV['GATEWAY_INTERFACE'] = 'CGI/1.1'
70
70
  env.keys.grep(/^HTTP_/) { |key| ENV[key] = env[key] }
71
71
 
72
- IO.new(0).reopen(inp)
73
- IO.new(1).reopen(out)
74
- IO.new(2).reopen(err)
72
+ a = IO.new(0).reopen(inp)
73
+ b = IO.new(1).reopen(out)
74
+ c = IO.new(2).reopen(err)
75
75
  exec(*@args)
76
76
  end
77
77
 
@@ -19,8 +19,8 @@ class Unicorn::App::OldRails
19
19
  cgi.body)
20
20
  rescue Object => e
21
21
  err = env['rack.errors']
22
- out.write("#{e} #{e.message}\n")
23
- e.backtrace.each { |line| out.write("#{line}\n") }
22
+ err.write("#{e} #{e.message}\n")
23
+ e.backtrace.each { |line| err.write("#{line}\n") }
24
24
  end
25
25
  cgi.out # finalize the response
26
26
  cgi.rack_response
@@ -143,12 +143,14 @@ module Unicorn
143
143
  # handling the request/app.call/response cycle taking longer than
144
144
  # this time period will be forcibly killed (via SIGKILL). This
145
145
  # timeout is enforced by the master process itself and not subject
146
- # to the scheduling limitations by the worker process.
146
+ # to the scheduling limitations by the worker process. Due the
147
+ # low-complexity, low-overhead implementation, timeouts of less
148
+ # than 3.0 seconds can be considered inaccurate and unsafe.
147
149
  def timeout(seconds)
148
150
  Numeric === seconds or raise ArgumentError,
149
151
  "not numeric: timeout=#{seconds.inspect}"
150
- seconds > 0 or raise ArgumentError,
151
- "not positive: timeout=#{seconds.inspect}"
152
+ seconds >= 3 or raise ArgumentError,
153
+ "too low: timeout=#{seconds.inspect}"
152
154
  @set[:timeout] = seconds
153
155
  end
154
156
 
@@ -179,32 +181,32 @@ module Unicorn
179
181
  #
180
182
  # +backlog+: this is the backlog of the listen() syscall.
181
183
  #
182
- # Some operating systems allow negative values here to specify the
183
- # maximum allowable value. In most cases, this number is only
184
- # recommendation and there are other OS-specific tunables and
185
- # variables that can affect this number. See the listen(2)
186
- # syscall documentation of your OS for the exact semantics of
187
- # this.
184
+ # Some operating systems allow negative values here to specify the
185
+ # maximum allowable value. In most cases, this number is only
186
+ # recommendation and there are other OS-specific tunables and
187
+ # variables that can affect this number. See the listen(2)
188
+ # syscall documentation of your OS for the exact semantics of
189
+ # this.
188
190
  #
189
- # If you are running unicorn on multiple machines, lowering this number
190
- # can help your load balancer detect when a machine is overloaded
191
- # and give requests to a different machine.
191
+ # If you are running unicorn on multiple machines, lowering this number
192
+ # can help your load balancer detect when a machine is overloaded
193
+ # and give requests to a different machine.
192
194
  #
193
- # Default: 1024
195
+ # Default: 1024
194
196
  #
195
197
  # +rcvbuf+, +sndbuf+: maximum send and receive buffer sizes of sockets
196
198
  #
197
- # These correspond to the SO_RCVBUF and SO_SNDBUF settings which
198
- # can be set via the setsockopt(2) syscall. Some kernels
199
- # (e.g. Linux 2.4+) have intelligent auto-tuning mechanisms and
200
- # there is no need (and it is sometimes detrimental) to specify them.
199
+ # These correspond to the SO_RCVBUF and SO_SNDBUF settings which
200
+ # can be set via the setsockopt(2) syscall. Some kernels
201
+ # (e.g. Linux 2.4+) have intelligent auto-tuning mechanisms and
202
+ # there is no need (and it is sometimes detrimental) to specify them.
201
203
  #
202
- # See the socket API documentation of your operating system
203
- # to determine the exact semantics of these settings and
204
- # other operating system-specific knobs where they can be
205
- # specified.
204
+ # See the socket API documentation of your operating system
205
+ # to determine the exact semantics of these settings and
206
+ # other operating system-specific knobs where they can be
207
+ # specified.
206
208
  #
207
- # Defaults: operating system defaults
209
+ # Defaults: operating system defaults
208
210
  def listen(address, opt = { :backlog => 1024 })
209
211
  address = expand_addr(address)
210
212
  if String === address
@@ -59,7 +59,7 @@ module Unicorn
59
59
  REQUEST_URI='REQUEST_URI'.freeze
60
60
  REQUEST_PATH='REQUEST_PATH'.freeze
61
61
 
62
- UNICORN_VERSION="0.7.0".freeze
62
+ UNICORN_VERSION="0.7.1".freeze
63
63
 
64
64
  DEFAULT_HOST = "0.0.0.0".freeze # default TCP listen host address
65
65
  DEFAULT_PORT = "8080".freeze # default TCP listen port
@@ -31,7 +31,7 @@ module Unicorn
31
31
  # writes the rack_response to socket as an HTTP response
32
32
  def self.write(socket, rack_response)
33
33
  status, headers, body = rack_response
34
- status = HTTP_STATUS_CODES[status]
34
+ status = HTTP_STATUS_CODES[status.to_i]
35
35
  OUT.clear
36
36
 
37
37
  # Don't bother enforcing duplicate supression, it's a Hash most of
@@ -4,6 +4,8 @@ module Unicorn
4
4
  class Util
5
5
  class << self
6
6
 
7
+ APPEND_FLAGS = File::WRONLY | File::APPEND
8
+
7
9
  # this reopens logs that have been rotated (using logrotate(8) or
8
10
  # similar). It is recommended that you install
9
11
  # A +File+ object is considered for reopening if it is:
@@ -17,17 +19,20 @@ module Unicorn
17
19
  ObjectSpace.each_object(File) do |fp|
18
20
  next if fp.closed?
19
21
  next unless (fp.sync && fp.path[0..0] == "/")
20
-
21
- flags = fp.fcntl(Fcntl::F_GETFL)
22
- open_flags = File::WRONLY | File::APPEND
23
- next unless (flags & open_flags) == open_flags
22
+ next unless (fp.fcntl(Fcntl::F_GETFL) & APPEND_FLAGS) == APPEND_FLAGS
24
23
 
25
24
  begin
26
25
  a, b = fp.stat, File.stat(fp.path)
27
26
  next if a.ino == b.ino && a.dev == b.dev
28
27
  rescue Errno::ENOENT
29
28
  end
30
- fp.reopen(fp.path, "a")
29
+
30
+ open_arg = 'a'
31
+ if fp.respond_to?(:external_encoding) && enc = fp.external_encoding
32
+ open_arg << ":#{enc.to_s}"
33
+ enc = fp.internal_encoding and open_arg << ":#{enc.to_s}"
34
+ end
35
+ fp.reopen(fp.path, open_arg)
31
36
  fp.sync = true
32
37
  nr += 1
33
38
  end # each_object
@@ -1,11 +1,6 @@
1
1
  # Copyright (c) 2009 Eric Wong
2
2
  # You can redistribute it and/or modify it under the same terms as Ruby.
3
3
 
4
- if RUBY_VERSION =~ /1\.9/
5
- warn "#$0 current broken under Ruby 1.9 with Rack"
6
- exit 0
7
- end
8
-
9
4
  require 'test/test_helper'
10
5
  begin
11
6
  require 'rack'
@@ -18,11 +18,19 @@ class ResponseTest < Test::Unit::TestCase
18
18
  assert out.length > 0, "output didn't have data"
19
19
  end
20
20
 
21
+ def test_response_string_status
22
+ out = StringIO.new
23
+ HttpResponse.write(out,['200', {}, []])
24
+ assert out.closed?
25
+ assert out.length > 0, "output didn't have data"
26
+ assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/).size
27
+ end
28
+
21
29
  def test_response_OFS_set
22
30
  old_ofs = $,
23
31
  $, = "\f\v"
24
32
  out = StringIO.new
25
- HttpResponse.write(out,[200, {"X-Whatever" => "stuff"}, ["cool"]])
33
+ HttpResponse.write(out,[200, {"X-k" => "cd","X-y" => "z"}, ["cool"]])
26
34
  assert out.closed?
27
35
  resp = out.string
28
36
  assert ! resp.include?("\f\v"), "output didn't use $, ($OFS)"
@@ -19,12 +19,28 @@ class UploadTest < Test::Unit::TestCase
19
19
  @sha1_app = lambda do |env|
20
20
  input = env['rack.input']
21
21
  resp = { :pos => input.pos, :size => input.size, :class => input.class }
22
+
23
+ # sysread
22
24
  @sha1.reset
23
25
  begin
24
26
  loop { @sha1.update(input.sysread(@bs)) }
25
27
  rescue EOFError
26
28
  end
27
29
  resp[:sha1] = @sha1.hexdigest
30
+
31
+ # read
32
+ input.sysseek(0) if input.respond_to?(:sysseek)
33
+ input.rewind
34
+ @sha1.reset
35
+ loop {
36
+ buf = input.read(@bs) or break
37
+ @sha1.update(buf)
38
+ }
39
+
40
+ if resp[:sha1] == @sha1.hexdigest
41
+ resp[:sysread_read_byte_match] = true
42
+ end
43
+
28
44
  [ 200, @hdr.merge({'X-Resp' => resp.inspect}), [] ]
29
45
  end
30
46
  end
@@ -218,6 +234,7 @@ class UploadTest < Test::Unit::TestCase
218
234
  assert $?.success?, 'curl ran OK'
219
235
  assert_match(%r!\b#{sha1}\b!, resp)
220
236
  assert_match(/Tempfile/, resp)
237
+ assert_match(/sysread_read_byte_match/, resp)
221
238
 
222
239
  # small StringIO path
223
240
  assert(system("dd", "if=#{@random.path}", "of=#{tmp.path}",
@@ -233,6 +250,7 @@ class UploadTest < Test::Unit::TestCase
233
250
  assert $?.success?, 'curl ran OK'
234
251
  assert_match(%r!\b#{sha1}\b!, resp)
235
252
  assert_match(/StringIO/, resp)
253
+ assert_match(/sysread_read_byte_match/, resp)
236
254
  end
237
255
 
238
256
  private
@@ -0,0 +1,87 @@
1
+ require 'test/test_helper'
2
+ require 'tempfile'
3
+
4
+ class TestUtil < Test::Unit::TestCase
5
+
6
+ EXPECT_FLAGS = File::WRONLY | File::APPEND
7
+ def test_reopen_logs_noop
8
+ tmp = Tempfile.new(nil)
9
+ tmp.reopen(tmp.path, 'a')
10
+ tmp.sync = true
11
+ ext = tmp.external_encoding rescue nil
12
+ int = tmp.internal_encoding rescue nil
13
+ before = tmp.stat.inspect
14
+ Unicorn::Util.reopen_logs
15
+ assert_equal before, File.stat(tmp.path).inspect
16
+ assert_equal ext, (tmp.external_encoding rescue nil)
17
+ assert_equal int, (tmp.internal_encoding rescue nil)
18
+ end
19
+
20
+ def test_reopen_logs_renamed
21
+ tmp = Tempfile.new(nil)
22
+ tmp_path = tmp.path.freeze
23
+ tmp.reopen(tmp_path, 'a')
24
+ tmp.sync = true
25
+ ext = tmp.external_encoding rescue nil
26
+ int = tmp.internal_encoding rescue nil
27
+ before = tmp.stat.inspect
28
+ to = Tempfile.new(nil)
29
+ File.rename(tmp_path, to.path)
30
+ assert ! File.exist?(tmp_path)
31
+ Unicorn::Util.reopen_logs
32
+ assert_equal tmp_path, tmp.path
33
+ assert File.exist?(tmp_path)
34
+ assert before != File.stat(tmp_path).inspect
35
+ assert_equal tmp.stat.inspect, File.stat(tmp_path).inspect
36
+ assert_equal ext, (tmp.external_encoding rescue nil)
37
+ assert_equal int, (tmp.internal_encoding rescue nil)
38
+ assert_equal(EXPECT_FLAGS, EXPECT_FLAGS & tmp.fcntl(Fcntl::F_GETFL))
39
+ assert tmp.sync
40
+ end
41
+
42
+ def test_reopen_logs_renamed_with_encoding
43
+ tmp = Tempfile.new(nil)
44
+ tmp_path = tmp.path.dup.freeze
45
+ Encoding.list.each { |encoding|
46
+ tmp.reopen(tmp_path, "a:#{encoding.to_s}")
47
+ tmp.sync = true
48
+ assert_equal encoding, tmp.external_encoding
49
+ assert_nil tmp.internal_encoding
50
+ File.unlink(tmp_path)
51
+ assert ! File.exist?(tmp_path)
52
+ Unicorn::Util.reopen_logs
53
+ assert_equal tmp_path, tmp.path
54
+ assert File.exist?(tmp_path)
55
+ assert_equal tmp.stat.inspect, File.stat(tmp_path).inspect
56
+ assert_equal encoding, tmp.external_encoding
57
+ assert_nil tmp.internal_encoding
58
+ assert_equal(EXPECT_FLAGS, EXPECT_FLAGS & tmp.fcntl(Fcntl::F_GETFL))
59
+ assert tmp.sync
60
+ }
61
+ end if STDIN.respond_to?(:external_encoding)
62
+
63
+ def test_reopen_logs_renamed_with_internal_encoding
64
+ tmp = Tempfile.new(nil)
65
+ tmp_path = tmp.path.dup.freeze
66
+ Encoding.list.each { |ext|
67
+ Encoding.list.each { |int|
68
+ next if ext == int
69
+ tmp.reopen(tmp_path, "a:#{ext.to_s}:#{int.to_s}")
70
+ tmp.sync = true
71
+ assert_equal ext, tmp.external_encoding
72
+ assert_equal int, tmp.internal_encoding
73
+ File.unlink(tmp_path)
74
+ assert ! File.exist?(tmp_path)
75
+ Unicorn::Util.reopen_logs
76
+ assert_equal tmp_path, tmp.path
77
+ assert File.exist?(tmp_path)
78
+ assert_equal tmp.stat.inspect, File.stat(tmp_path).inspect
79
+ assert_equal ext, tmp.external_encoding
80
+ assert_equal int, tmp.internal_encoding
81
+ assert_equal(EXPECT_FLAGS, EXPECT_FLAGS & tmp.fcntl(Fcntl::F_GETFL))
82
+ assert tmp.sync
83
+ }
84
+ }
85
+ end if STDIN.respond_to?(:external_encoding)
86
+
87
+ end
@@ -2,29 +2,29 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{unicorn}
5
- s.version = "0.7.0"
5
+ s.version = "0.7.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Eric Wong"]
9
- s.date = %q{2009-04-25}
9
+ s.date = %q{2009-05-22}
10
10
  s.description = %q{A small fast HTTP library and server for Rack applications.}
11
11
  s.email = %q{normalperson@yhbt.net}
12
12
  s.executables = ["unicorn", "unicorn_rails"]
13
13
  s.extensions = ["ext/unicorn/http11/extconf.rb"]
14
14
  s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "TODO", "bin/unicorn", "bin/unicorn_rails", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/app/exec_cgi.rb", "lib/unicorn/app/old_rails.rb", "lib/unicorn/app/old_rails/static.rb", "lib/unicorn/cgi_wrapper.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/launcher.rb", "lib/unicorn/socket_helper.rb", "lib/unicorn/util.rb"]
15
- s.files = [".document", ".gitignore", "CHANGELOG", "CONTRIBUTORS", "DESIGN", "GNUmakefile", "LICENSE", "Manifest", "PHILOSOPHY", "README", "Rakefile", "SIGNALS", "TODO", "bin/unicorn", "bin/unicorn_rails", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/app/exec_cgi.rb", "lib/unicorn/app/old_rails.rb", "lib/unicorn/app/old_rails/static.rb", "lib/unicorn/cgi_wrapper.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/launcher.rb", "lib/unicorn/socket_helper.rb", "lib/unicorn/util.rb", "local.mk.sample", "setup.rb", "test/aggregate.rb", "test/benchmark/README", "test/benchmark/big_request.rb", "test/benchmark/dd.ru", "test/benchmark/request.rb", "test/benchmark/response.rb", "test/exec/README", "test/exec/test_exec.rb", "test/rails/app-1.2.3/.gitignore", "test/rails/app-1.2.3/Rakefile", "test/rails/app-1.2.3/app/controllers/application.rb", "test/rails/app-1.2.3/app/controllers/foo_controller.rb", "test/rails/app-1.2.3/app/helpers/application_helper.rb", "test/rails/app-1.2.3/config/boot.rb", "test/rails/app-1.2.3/config/database.yml", "test/rails/app-1.2.3/config/environment.rb", "test/rails/app-1.2.3/config/environments/development.rb", "test/rails/app-1.2.3/config/environments/production.rb", "test/rails/app-1.2.3/config/routes.rb", "test/rails/app-1.2.3/db/.gitignore", "test/rails/app-1.2.3/log/.gitignore", "test/rails/app-1.2.3/public/404.html", "test/rails/app-1.2.3/public/500.html", "test/rails/app-2.0.2/.gitignore", "test/rails/app-2.0.2/Rakefile", "test/rails/app-2.0.2/app/controllers/application.rb", "test/rails/app-2.0.2/app/controllers/foo_controller.rb", "test/rails/app-2.0.2/app/helpers/application_helper.rb", "test/rails/app-2.0.2/config/boot.rb", "test/rails/app-2.0.2/config/database.yml", "test/rails/app-2.0.2/config/environment.rb", "test/rails/app-2.0.2/config/environments/development.rb", "test/rails/app-2.0.2/config/environments/production.rb", "test/rails/app-2.0.2/config/routes.rb", "test/rails/app-2.0.2/db/.gitignore", "test/rails/app-2.0.2/log/.gitignore", "test/rails/app-2.0.2/public/404.html", "test/rails/app-2.0.2/public/500.html", "test/rails/app-2.1.2/.gitignore", "test/rails/app-2.1.2/Rakefile", "test/rails/app-2.1.2/app/controllers/application.rb", "test/rails/app-2.1.2/app/controllers/foo_controller.rb", "test/rails/app-2.1.2/app/helpers/application_helper.rb", "test/rails/app-2.1.2/config/boot.rb", "test/rails/app-2.1.2/config/database.yml", "test/rails/app-2.1.2/config/environment.rb", "test/rails/app-2.1.2/config/environments/development.rb", "test/rails/app-2.1.2/config/environments/production.rb", "test/rails/app-2.1.2/config/routes.rb", "test/rails/app-2.1.2/db/.gitignore", "test/rails/app-2.1.2/log/.gitignore", "test/rails/app-2.1.2/public/404.html", "test/rails/app-2.1.2/public/500.html", "test/rails/app-2.2.2/.gitignore", "test/rails/app-2.2.2/Rakefile", "test/rails/app-2.2.2/app/controllers/application.rb", "test/rails/app-2.2.2/app/controllers/foo_controller.rb", "test/rails/app-2.2.2/app/helpers/application_helper.rb", "test/rails/app-2.2.2/config/boot.rb", "test/rails/app-2.2.2/config/database.yml", "test/rails/app-2.2.2/config/environment.rb", "test/rails/app-2.2.2/config/environments/development.rb", "test/rails/app-2.2.2/config/environments/production.rb", "test/rails/app-2.2.2/config/routes.rb", "test/rails/app-2.2.2/db/.gitignore", "test/rails/app-2.2.2/log/.gitignore", "test/rails/app-2.2.2/public/404.html", "test/rails/app-2.2.2/public/500.html", "test/rails/app-2.3.2.1/.gitignore", "test/rails/app-2.3.2.1/Rakefile", "test/rails/app-2.3.2.1/app/controllers/application_controller.rb", "test/rails/app-2.3.2.1/app/controllers/foo_controller.rb", "test/rails/app-2.3.2.1/app/helpers/application_helper.rb", "test/rails/app-2.3.2.1/config/boot.rb", "test/rails/app-2.3.2.1/config/database.yml", "test/rails/app-2.3.2.1/config/environment.rb", "test/rails/app-2.3.2.1/config/environments/development.rb", "test/rails/app-2.3.2.1/config/environments/production.rb", "test/rails/app-2.3.2.1/config/routes.rb", "test/rails/app-2.3.2.1/db/.gitignore", "test/rails/app-2.3.2.1/log/.gitignore", "test/rails/app-2.3.2.1/public/404.html", "test/rails/app-2.3.2.1/public/500.html", "test/rails/test_rails.rb", "test/test_helper.rb", "test/tools/trickletest.rb", "test/unit/test_configurator.rb", "test/unit/test_http_parser.rb", "test/unit/test_request.rb", "test/unit/test_response.rb", "test/unit/test_server.rb", "test/unit/test_signals.rb", "test/unit/test_socket_helper.rb", "test/unit/test_upload.rb", "unicorn.gemspec"]
15
+ s.files = [".document", ".gitignore", "CHANGELOG", "CONTRIBUTORS", "DESIGN", "GNUmakefile", "LICENSE", "Manifest", "PHILOSOPHY", "README", "Rakefile", "SIGNALS", "TODO", "TUNING", "bin/unicorn", "bin/unicorn_rails", "examples/init.sh", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/app/exec_cgi.rb", "lib/unicorn/app/old_rails.rb", "lib/unicorn/app/old_rails/static.rb", "lib/unicorn/cgi_wrapper.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/launcher.rb", "lib/unicorn/socket_helper.rb", "lib/unicorn/util.rb", "local.mk.sample", "setup.rb", "test/aggregate.rb", "test/benchmark/README", "test/benchmark/big_request.rb", "test/benchmark/dd.ru", "test/benchmark/request.rb", "test/benchmark/response.rb", "test/exec/README", "test/exec/test_exec.rb", "test/rails/app-1.2.3/.gitignore", "test/rails/app-1.2.3/Rakefile", "test/rails/app-1.2.3/app/controllers/application.rb", "test/rails/app-1.2.3/app/controllers/foo_controller.rb", "test/rails/app-1.2.3/app/helpers/application_helper.rb", "test/rails/app-1.2.3/config/boot.rb", "test/rails/app-1.2.3/config/database.yml", "test/rails/app-1.2.3/config/environment.rb", "test/rails/app-1.2.3/config/environments/development.rb", "test/rails/app-1.2.3/config/environments/production.rb", "test/rails/app-1.2.3/config/routes.rb", "test/rails/app-1.2.3/db/.gitignore", "test/rails/app-1.2.3/log/.gitignore", "test/rails/app-1.2.3/public/404.html", "test/rails/app-1.2.3/public/500.html", "test/rails/app-2.0.2/.gitignore", "test/rails/app-2.0.2/Rakefile", "test/rails/app-2.0.2/app/controllers/application.rb", "test/rails/app-2.0.2/app/controllers/foo_controller.rb", "test/rails/app-2.0.2/app/helpers/application_helper.rb", "test/rails/app-2.0.2/config/boot.rb", "test/rails/app-2.0.2/config/database.yml", "test/rails/app-2.0.2/config/environment.rb", "test/rails/app-2.0.2/config/environments/development.rb", "test/rails/app-2.0.2/config/environments/production.rb", "test/rails/app-2.0.2/config/routes.rb", "test/rails/app-2.0.2/db/.gitignore", "test/rails/app-2.0.2/log/.gitignore", "test/rails/app-2.0.2/public/404.html", "test/rails/app-2.0.2/public/500.html", "test/rails/app-2.1.2/.gitignore", "test/rails/app-2.1.2/Rakefile", "test/rails/app-2.1.2/app/controllers/application.rb", "test/rails/app-2.1.2/app/controllers/foo_controller.rb", "test/rails/app-2.1.2/app/helpers/application_helper.rb", "test/rails/app-2.1.2/config/boot.rb", "test/rails/app-2.1.2/config/database.yml", "test/rails/app-2.1.2/config/environment.rb", "test/rails/app-2.1.2/config/environments/development.rb", "test/rails/app-2.1.2/config/environments/production.rb", "test/rails/app-2.1.2/config/routes.rb", "test/rails/app-2.1.2/db/.gitignore", "test/rails/app-2.1.2/log/.gitignore", "test/rails/app-2.1.2/public/404.html", "test/rails/app-2.1.2/public/500.html", "test/rails/app-2.2.2/.gitignore", "test/rails/app-2.2.2/Rakefile", "test/rails/app-2.2.2/app/controllers/application.rb", "test/rails/app-2.2.2/app/controllers/foo_controller.rb", "test/rails/app-2.2.2/app/helpers/application_helper.rb", "test/rails/app-2.2.2/config/boot.rb", "test/rails/app-2.2.2/config/database.yml", "test/rails/app-2.2.2/config/environment.rb", "test/rails/app-2.2.2/config/environments/development.rb", "test/rails/app-2.2.2/config/environments/production.rb", "test/rails/app-2.2.2/config/routes.rb", "test/rails/app-2.2.2/db/.gitignore", "test/rails/app-2.2.2/log/.gitignore", "test/rails/app-2.2.2/public/404.html", "test/rails/app-2.2.2/public/500.html", "test/rails/app-2.3.2.1/.gitignore", "test/rails/app-2.3.2.1/Rakefile", "test/rails/app-2.3.2.1/app/controllers/application_controller.rb", "test/rails/app-2.3.2.1/app/controllers/foo_controller.rb", "test/rails/app-2.3.2.1/app/helpers/application_helper.rb", "test/rails/app-2.3.2.1/config/boot.rb", "test/rails/app-2.3.2.1/config/database.yml", "test/rails/app-2.3.2.1/config/environment.rb", "test/rails/app-2.3.2.1/config/environments/development.rb", "test/rails/app-2.3.2.1/config/environments/production.rb", "test/rails/app-2.3.2.1/config/routes.rb", "test/rails/app-2.3.2.1/db/.gitignore", "test/rails/app-2.3.2.1/log/.gitignore", "test/rails/app-2.3.2.1/public/404.html", "test/rails/app-2.3.2.1/public/500.html", "test/rails/test_rails.rb", "test/test_helper.rb", "test/tools/trickletest.rb", "test/unit/test_configurator.rb", "test/unit/test_http_parser.rb", "test/unit/test_request.rb", "test/unit/test_response.rb", "test/unit/test_server.rb", "test/unit/test_signals.rb", "test/unit/test_socket_helper.rb", "test/unit/test_upload.rb", "test/unit/test_util.rb", "unicorn.gemspec"]
16
16
  s.has_rdoc = true
17
17
  s.homepage = %q{http://unicorn.bogomips.org}
18
18
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Unicorn", "--main", "README"]
19
19
  s.require_paths = ["lib", "ext"]
20
20
  s.rubyforge_project = %q{unicorn}
21
- s.rubygems_version = %q{1.3.1}
21
+ s.rubygems_version = %q{1.3.2}
22
22
  s.summary = %q{A small fast HTTP library and server for Rack applications.}
23
- s.test_files = ["test/unit/test_request.rb", "test/unit/test_http_parser.rb", "test/unit/test_server.rb", "test/unit/test_response.rb", "test/unit/test_configurator.rb", "test/unit/test_upload.rb", "test/unit/test_signals.rb", "test/unit/test_socket_helper.rb"]
23
+ s.test_files = ["test/unit/test_configurator.rb", "test/unit/test_response.rb", "test/unit/test_request.rb", "test/unit/test_signals.rb", "test/unit/test_upload.rb", "test/unit/test_http_parser.rb", "test/unit/test_socket_helper.rb", "test/unit/test_util.rb", "test/unit/test_server.rb"]
24
24
 
25
25
  if s.respond_to? :specification_version then
26
26
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
27
- s.specification_version = 2
27
+ s.specification_version = 3
28
28
 
29
29
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
30
30
  else
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unicorn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Wong
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-25 00:00:00 -07:00
12
+ date: 2009-05-22 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -59,8 +59,10 @@ files:
59
59
  - Rakefile
60
60
  - SIGNALS
61
61
  - TODO
62
+ - TUNING
62
63
  - bin/unicorn
63
64
  - bin/unicorn_rails
65
+ - examples/init.sh
64
66
  - ext/unicorn/http11/ext_help.h
65
67
  - ext/unicorn/http11/extconf.rb
66
68
  - ext/unicorn/http11/http11.c
@@ -175,9 +177,12 @@ files:
175
177
  - test/unit/test_signals.rb
176
178
  - test/unit/test_socket_helper.rb
177
179
  - test/unit/test_upload.rb
180
+ - test/unit/test_util.rb
178
181
  - unicorn.gemspec
179
182
  has_rdoc: true
180
183
  homepage: http://unicorn.bogomips.org
184
+ licenses: []
185
+
181
186
  post_install_message:
182
187
  rdoc_options:
183
188
  - --line-numbers
@@ -204,16 +209,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
204
209
  requirements: []
205
210
 
206
211
  rubyforge_project: unicorn
207
- rubygems_version: 1.3.1
212
+ rubygems_version: 1.3.2
208
213
  signing_key:
209
- specification_version: 2
214
+ specification_version: 3
210
215
  summary: A small fast HTTP library and server for Rack applications.
211
216
  test_files:
212
- - test/unit/test_request.rb
213
- - test/unit/test_http_parser.rb
214
- - test/unit/test_server.rb
215
- - test/unit/test_response.rb
216
217
  - test/unit/test_configurator.rb
217
- - test/unit/test_upload.rb
218
+ - test/unit/test_response.rb
219
+ - test/unit/test_request.rb
218
220
  - test/unit/test_signals.rb
221
+ - test/unit/test_upload.rb
222
+ - test/unit/test_http_parser.rb
219
223
  - test/unit/test_socket_helper.rb
224
+ - test/unit/test_util.rb
225
+ - test/unit/test_server.rb