thin 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of thin might be problematic. Click here for more details.

Files changed (57) hide show
  1. data/CHANGELOG +15 -0
  2. data/README +10 -4
  3. data/benchmark/abc +0 -0
  4. data/benchmark/runner +0 -0
  5. data/bin/thin +0 -0
  6. data/example/thin_solaris_smf.erb +36 -0
  7. data/example/thin_solaris_smf.readme.txt +150 -0
  8. data/ext/thin_parser/common.rl +3 -2
  9. data/ext/thin_parser/parser.c +15 -38
  10. data/lib/rack/adapter/loader.rb +69 -0
  11. data/lib/rack/adapter/rails.rb +17 -8
  12. data/lib/thin.rb +1 -0
  13. data/lib/thin/backends/base.rb +17 -0
  14. data/lib/thin/backends/swiftiply_client.rb +3 -2
  15. data/lib/thin/backends/tcp_server.rb +1 -1
  16. data/lib/thin/connection.rb +38 -6
  17. data/lib/thin/controllers/controller.rb +43 -17
  18. data/lib/thin/logging.rb +1 -1
  19. data/lib/thin/request.rb +8 -1
  20. data/lib/thin/runner.rb +29 -7
  21. data/lib/thin/server.rb +58 -28
  22. data/lib/thin/version.rb +3 -3
  23. data/lib/thin_backend.bundle +0 -0
  24. data/lib/thin_parser.bundle +0 -0
  25. data/spec/connection_spec.rb +7 -0
  26. data/spec/controllers/controller_spec.rb +9 -1
  27. data/spec/rack/loader_spec.rb +29 -0
  28. data/spec/{rack_rails_spec.rb → rack/rails_adapter_spec.rb} +15 -3
  29. data/spec/rails_app/public/dispatch.cgi +0 -0
  30. data/spec/rails_app/public/dispatch.fcgi +0 -0
  31. data/spec/rails_app/public/dispatch.rb +0 -0
  32. data/spec/rails_app/script/about +0 -0
  33. data/spec/rails_app/script/console +0 -0
  34. data/spec/rails_app/script/destroy +0 -0
  35. data/spec/rails_app/script/generate +0 -0
  36. data/spec/rails_app/script/performance/benchmarker +0 -0
  37. data/spec/rails_app/script/performance/profiler +0 -0
  38. data/spec/rails_app/script/performance/request +0 -0
  39. data/spec/rails_app/script/plugin +0 -0
  40. data/spec/rails_app/script/process/inspector +0 -0
  41. data/spec/rails_app/script/process/reaper +0 -0
  42. data/spec/rails_app/script/process/spawner +0 -0
  43. data/spec/rails_app/script/runner +0 -0
  44. data/spec/rails_app/script/server +0 -0
  45. data/spec/request/parser_spec.rb +22 -0
  46. data/spec/request/processing_spec.rb +9 -10
  47. data/spec/runner_spec.rb +14 -1
  48. data/spec/server/builder_spec.rb +3 -2
  49. data/spec/server/robustness_spec.rb +34 -0
  50. data/spec/server/swiftiply_spec.rb +1 -1
  51. data/spec/server/threaded_spec.rb +27 -0
  52. data/spec/server_spec.rb +69 -0
  53. data/spec/spec_helper.rb +10 -5
  54. data/tasks/gem.rake +2 -2
  55. data/tasks/spec.rake +24 -16
  56. metadata +13 -5
  57. data/doc/benchmarks.txt +0 -86
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Server, 'robustness' do
4
+ before do
5
+ start_server do |env|
6
+ body = 'hello!'
7
+ [200, { 'Content-Type' => 'text/html', 'Content-Length' => body.size.to_s }, body]
8
+ end
9
+ end
10
+
11
+ it "should not crash when header too large" do
12
+ 100.times do
13
+ begin
14
+ socket = TCPSocket.new(DEFAULT_TEST_ADDRESS, DEFAULT_TEST_PORT)
15
+ socket.write("GET / HTTP/1.1\r\n")
16
+ socket.write("Host: localhost\r\n")
17
+ socket.write("Connection: close\r\n")
18
+ 10000.times do
19
+ socket.write("X-Foo: #{'x' * 100}\r\n")
20
+ socket.flush
21
+ end
22
+ socket.write("\r\n")
23
+ socket.read
24
+ socket.close
25
+ rescue Errno::EPIPE, Errno::ECONNRESET
26
+ # Ignore.
27
+ end
28
+ end
29
+ end
30
+
31
+ after do
32
+ stop_server
33
+ end
34
+ end
@@ -10,7 +10,7 @@ else
10
10
  end
11
11
  wait_for_socket('0.0.0.0', 3333)
12
12
  sleep 2 # HACK ooh boy, I wish I knew how to make those specs more stable...
13
- start_server(Backends::SwiftiplyClient.new('0.0.0.0', 5555, nil), nil, false) do |env|
13
+ start_server('0.0.0.0', 5555, :backend => Backends::SwiftiplyClient, :wait_for_socket => false) do |env|
14
14
  body = env.inspect + env['rack.input'].read
15
15
  [200, { 'Content-Type' => 'text/html', 'Content-Length' => body.size.to_s }, body]
16
16
  end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Server, 'with threads' do
4
+ before do
5
+ @requests = 0
6
+ start_server DEFAULT_TEST_ADDRESS, DEFAULT_TEST_PORT, :threaded => true do |env|
7
+ sleep env['PATH_INFO'].delete('/').to_i
8
+ @requests += 1
9
+ [200, { 'Content-Type' => 'text/html', 'Content-Length' => '2' }, 'hi']
10
+ end
11
+ end
12
+
13
+ it "should process request" do
14
+ get('/').should_not be_empty
15
+ end
16
+
17
+ it "should process requests when blocked" do
18
+ slow_request = Thread.new { get('/3') }
19
+ get('/').should_not be_empty
20
+ @requests.should == 1
21
+ slow_request.kill
22
+ end
23
+
24
+ after do
25
+ stop_server
26
+ end
27
+ end
data/spec/server_spec.rb CHANGED
@@ -16,4 +16,73 @@ describe Server do
16
16
  @server.config
17
17
  @server.maximum_connections.should < 100_000
18
18
  end
19
+
20
+ it "should default to non-threaded" do
21
+ @server.should_not be_threaded
22
+ end
23
+
24
+ it "should set backend to threaded" do
25
+ @server.threaded = true
26
+ @server.backend.should be_threaded
27
+ end
28
+ end
29
+
30
+ describe Server, "initialization" do
31
+ it "should set host and port" do
32
+ server = Server.new('192.168.1.1', 8080)
33
+
34
+ server.host.should == '192.168.1.1'
35
+ server.port.should == 8080
36
+ end
37
+
38
+ it "should set socket" do
39
+ server = Server.new('/tmp/thin.sock')
40
+
41
+ server.socket.should == '/tmp/thin.sock'
42
+ end
43
+
44
+ it "should set host, port and app" do
45
+ app = proc {}
46
+ server = Server.new('192.168.1.1', 8080, app)
47
+
48
+ server.host.should_not be_nil
49
+ server.app.should == app
50
+ end
51
+
52
+ it "should set socket and app" do
53
+ app = proc {}
54
+ server = Server.new('/tmp/thin.sock', app)
55
+
56
+ server.socket.should_not be_nil
57
+ server.app.should == app
58
+ end
59
+
60
+ it "should set socket, nil and app" do
61
+ app = proc {}
62
+ server = Server.new('/tmp/thin.sock', nil, app)
63
+
64
+ server.socket.should_not be_nil
65
+ server.app.should == app
66
+ end
67
+
68
+ it "should set host, port and backend" do
69
+ server = Server.new('192.168.1.1', 8080, :backend => Thin::Backends::SwiftiplyClient)
70
+
71
+ server.host.should_not be_nil
72
+ server.backend.should be_kind_of(Thin::Backends::SwiftiplyClient)
73
+ end
74
+
75
+ it "should set host, port, app and backend" do
76
+ app = proc {}
77
+ server = Server.new('192.168.1.1', 8080, app, :backend => Thin::Backends::SwiftiplyClient)
78
+
79
+ server.host.should_not be_nil
80
+ server.app.should == app
81
+ server.backend.should be_kind_of(Thin::Backends::SwiftiplyClient)
82
+ end
83
+
84
+ it "should not register signals w/ :signals => false" do
85
+ Server.should_not_receive(:setup_signals)
86
+ Server.new(:signals => false)
87
+ end
19
88
  end
data/spec/spec_helper.rb CHANGED
@@ -14,7 +14,11 @@ FileUtils.mkdir_p File.dirname(__FILE__) + '/../log'
14
14
  Command.script = File.dirname(__FILE__) + '/../bin/thin'
15
15
  Logging.silent = true
16
16
 
17
- SWIFTIPLY_PATH = `which swiftiply`.chomp unless Object.const_defined?(:SWIFTIPLY_PATH)
17
+ unless Object.const_defined?(:SWIFTIPLY_PATH)
18
+ SWIFTIPLY_PATH = `which swiftiply`.chomp
19
+ DEFAULT_TEST_ADDRESS = '0.0.0.0'
20
+ DEFAULT_TEST_PORT = 3333
21
+ end
18
22
 
19
23
  module Matchers
20
24
  class BeFasterThen
@@ -138,12 +142,13 @@ module Helpers
138
142
  request
139
143
  end
140
144
 
141
- def start_server(address='0.0.0.0', port=3333, wait_for_socket=true, &app)
142
- @server = Thin::Server.new(address, port, app)
145
+ def start_server(address=DEFAULT_TEST_ADDRESS, port=DEFAULT_TEST_PORT, options={}, &app)
146
+ @server = Thin::Server.new(address, port, options, app)
147
+ @server.threaded = options[:threaded]
143
148
  @server.timeout = 3
144
149
 
145
150
  @thread = Thread.new { @server.start }
146
- if wait_for_socket
151
+ if options[:wait_for_socket]
147
152
  wait_for_socket(address, port)
148
153
  else
149
154
  # If we can't ping the address fallback to just wait for the server to run
@@ -157,7 +162,7 @@ module Helpers
157
162
  raise "Reactor still running, wtf?" if EventMachine.reactor_running?
158
163
  end
159
164
 
160
- def wait_for_socket(address='0.0.0.0', port=3333, timeout=5)
165
+ def wait_for_socket(address=DEFAULT_TEST_ADDRESS, port=DEFAULT_TEST_PORT, timeout=5)
161
166
  Timeout.timeout(timeout) do
162
167
  loop do
163
168
  begin
data/tasks/gem.rake CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rake/gempackagetask'
2
2
 
3
- WIN_SUFFIX = ENV['WIN_SUFFIX'] || 'x86-mswin32-60'
3
+ WIN_SUFFIX = ENV['WIN_SUFFIX'] || 'i386-mswin32'
4
4
 
5
5
  task :clean => :clobber_package
6
6
 
@@ -21,7 +21,7 @@ spec = Gem::Specification.new do |s|
21
21
 
22
22
  s.add_dependency 'rack', '>= 0.2.0'
23
23
  if WIN
24
- s.add_dependency 'eventmachine', '>= 0.8.1'
24
+ s.add_dependency 'eventmachine', '= 0.8.1' # TODO replace w/ latest precompiled
25
25
  else
26
26
  s.add_dependency 'daemons', '>= 1.0.9'
27
27
  s.add_dependency 'eventmachine', '>= 0.10.0' # TODO '>= 0.11.0' when it's released
data/tasks/spec.rake CHANGED
@@ -7,26 +7,34 @@ if RUBY_1_9 # RSpec not yet working w/ Ruby 1.9
7
7
  else
8
8
  require 'spec/rake/spectask'
9
9
 
10
- desc "Run all examples"
11
- Spec::Rake::SpecTask.new(:spec) do |t|
12
- t.spec_opts = %w(-fs -c)
13
- t.spec_files = FileList['spec/**/*_spec.rb'] - FileList['spec/perf/*_spec.rb']
14
- if WIN
15
- t.spec_files -= [
16
- 'spec/backends/unix_server_spec.rb',
17
- 'spec/controllers/service_spec.rb',
18
- 'spec/daemonizing_spec.rb',
19
- 'spec/server/unix_socket_spec.rb',
20
- 'spec/server/swiftiply_spec.rb'
21
- ]
10
+ PERF_SPECS = FileList['spec/perf/*_spec.rb']
11
+ WIN_SPECS = %w(
12
+ spec/backends/unix_server_spec.rb
13
+ spec/controllers/service_spec.rb
14
+ spec/daemonizing_spec.rb
15
+ spec/server/unix_socket_spec.rb
16
+ spec/server/swiftiply_spec.rb
17
+ )
18
+ # HACK Event machine causes some problems when running multiple
19
+ # tests in the same VM so we split the specs in 2 before I find
20
+ # a better solution...
21
+ SPECS2 = %w(spec/server/threaded_spec.rb spec/server/tcp_spec.rb)
22
+ SPECS = FileList['spec/**/*_spec.rb'] - PERF_SPECS - SPECS2
23
+
24
+ def spec_task(name, specs)
25
+ Spec::Rake::SpecTask.new(name) do |t|
26
+ t.spec_opts = %w(-fs -c)
27
+ t.spec_files = specs
22
28
  end
23
29
  end
24
- task :spec => :compile
30
+
31
+ desc "Run all examples"
32
+ spec_task :spec, SPECS
33
+ spec_task :spec2, SPECS2
34
+ task :spec => [:compile, :spec2]
25
35
 
26
36
  desc "Run all performance examples"
27
- Spec::Rake::SpecTask.new('spec:perf') do |t|
28
- t.spec_files = FileList['spec/perf/*_spec.rb']
29
- end
37
+ spec_task 'spec:perf', PERF_SPECS
30
38
 
31
39
  task :check_benchmark_unit_gem do
32
40
  begin
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc-Andre Cournoyer
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-03-06 00:00:00 -05:00
12
+ date: 2008-04-06 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -57,16 +57,18 @@ files:
57
57
  - benchmark/benchmarker.rb
58
58
  - benchmark/runner
59
59
  - bin/thin
60
- - doc/benchmarks.txt
61
60
  - example/adapter.rb
62
61
  - example/config.ru
63
62
  - example/monit_sockets
64
63
  - example/monit_unixsock
65
64
  - example/ramaze.ru
66
65
  - example/thin.god
66
+ - example/thin_solaris_smf.erb
67
+ - example/thin_solaris_smf.readme.txt
67
68
  - example/vlad.rake
68
69
  - lib/rack
69
70
  - lib/rack/adapter
71
+ - lib/rack/adapter/loader.rb
70
72
  - lib/rack/adapter/rails.rb
71
73
  - lib/rack/handler
72
74
  - lib/rack/handler/thin.rb
@@ -95,6 +97,8 @@ files:
95
97
  - lib/thin/statuses.rb
96
98
  - lib/thin/version.rb
97
99
  - lib/thin.rb
100
+ - lib/thin_backend.bundle
101
+ - lib/thin_parser.bundle
98
102
  - spec/backends
99
103
  - spec/backends/swiftiply_client_spec.rb
100
104
  - spec/backends/tcp_server_spec.rb
@@ -115,7 +119,9 @@ files:
115
119
  - spec/perf/request_perf_spec.rb
116
120
  - spec/perf/response_perf_spec.rb
117
121
  - spec/perf/server_perf_spec.rb
118
- - spec/rack_rails_spec.rb
122
+ - spec/rack
123
+ - spec/rack/loader_spec.rb
124
+ - spec/rack/rails_adapter_spec.rb
119
125
  - spec/rails_app
120
126
  - spec/rails_app/app
121
127
  - spec/rails_app/app/controllers
@@ -185,10 +191,12 @@ files:
185
191
  - spec/server
186
192
  - spec/server/builder_spec.rb
187
193
  - spec/server/pipelining_spec.rb
194
+ - spec/server/robustness_spec.rb
188
195
  - spec/server/stopping_spec.rb
189
196
  - spec/server/swiftiply.yml
190
197
  - spec/server/swiftiply_spec.rb
191
198
  - spec/server/tcp_spec.rb
199
+ - spec/server/threaded_spec.rb
192
200
  - spec/server/unix_socket_spec.rb
193
201
  - spec/server_spec.rb
194
202
  - spec/spec_helper.rb
@@ -230,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
230
238
  requirements: []
231
239
 
232
240
  rubyforge_project: thin
233
- rubygems_version: 1.0.1
241
+ rubygems_version: 1.1.0
234
242
  signing_key:
235
243
  specification_version: 2
236
244
  summary: A thin and fast web server
data/doc/benchmarks.txt DELETED
@@ -1,86 +0,0 @@
1
- == Process
2
- * rackup ...
3
- * nice -n20 httperf --port 9292 --num-conns 9000
4
- * nice -n20 ab -n5000 localhost:9292/
5
- * nice -n20 ab -n5000 -c10 localhost:9292/
6
- * nice -n20 ab -n5000 -c100 localhost:9292/
7
-
8
- == More Benchmarks
9
- http://www.webficient.com/2007/08/testing-various-configurations-of-rails.html
10
-
11
- === WEBrick
12
- rackup -s webrick
13
-
14
- ==== httperf
15
- Reply rate [replies/s]: min 303.8 avg 306.8 max 310.4 stddev 2.8 (5 samples)
16
- Reply rate [replies/s]: min 235.8 avg 292.2 max 306.4 stddev 27.7 (6 samples)
17
- Reply rate [replies/s]: min 304.8 avg 306.9 max 308.8 stddev 1.5 (5 samples)
18
- avg: 302.0 10.7
19
-
20
- ==== Concurrency Level 1
21
- 297.37 [#/sec] (mean)
22
-
23
- ==== Concurrency Level 10
24
- 296.65 [#/sec] (mean) Failed requests: 4 (Connect: 2, Length: 2, Exceptions: 0)
25
- 298.22 [#/sec] (mean) Failed requests: 4 (Connect: 2, Length: 2, Exceptions: 0)
26
-
27
- ==== Concurrency Level 100
28
- 297.16 [#/sec] (mean) Failed requests: 489 (Connect: 245, Length: 244, Exceptions: 0)
29
-
30
-
31
- === Mongrel
32
- rackup -s mongrel
33
-
34
- ==== httperf
35
- Reply rate [replies/s]: min 556.4 avg 580.1 max 613.6 stddev 29.9 (3 samples)
36
- Reply rate [replies/s]: min 299.0 avg 502.6 max 613.4 stddev 176.5 (3 samples)
37
- Reply rate [replies/s]: min 601.0 avg 608.5 max 616.0 stddev 10.7 (2 samples)
38
- Reply rate [replies/s]: min 605.2 avg 608.4 max 611.6 stddev 4.5 (2 samples)
39
- avg: 574.9 55.4
40
-
41
- ==== Concurrency Level 1
42
- 556.67 [#/sec] (mean)
43
-
44
- ==== Concurrency Level 10
45
- 622.90 [#/sec] (mean)
46
-
47
- ==== Concurrency Level 100
48
- 428.23 [#/sec] (mean)
49
-
50
- === Evented Mongrel
51
- rackup -r "swiftcore/evented_mongrel" -s mongrel
52
-
53
- ==== httperf
54
- Reply rate [replies/s]: min 452.4 avg 541.0 max 590.0 stddev 76.9 (3 samples)
55
- Reply rate [replies/s]: min 573.2 avg 586.0 max 593.0 stddev 11.1 (3 samples)
56
- Reply rate [replies/s]: min 546.6 avg 574.8 max 594.6 stddev 25.0 (3 samples)
57
- Reply rate [replies/s]: min 593.6 avg 595.2 max 596.4 stddev 1.5 (3 samples)
58
- avg: 574.25 28.625
59
-
60
- ==== Concurrency Level 1
61
- 517.97 [#/sec] (mean)
62
-
63
- ==== Concurrency Level 10
64
- 657.89 [#/sec] (mean)
65
-
66
- ==== Concurrency Level 100
67
- 656.17 [#/sec] (mean)
68
-
69
- === Thin
70
- rackup -s thin
71
-
72
- ==== httperf
73
- Reply rate [replies/s]: min 671.4 avg 681.0 max 690.7 stddev 13.6 (2 samples)
74
- Reply rate [replies/s]: min 690.0 avg 695.8 max 701.7 stddev 8.3 (2 samples)
75
- Reply rate [replies/s]: min 643.4 avg 669.4 max 695.4 stddev 36.7 (2 samples)
76
- Reply rate [replies/s]: min 694.1 avg 695.8 max 697.6 stddev 2.5 (2 samples)
77
- avg: 685.5 15.275
78
-
79
- ==== Concurrency Level 1
80
- 719.53 [#/sec] (mean)
81
-
82
- ==== Concurrency Level 10
83
- 782.11 [#/sec] (mean)
84
-
85
- ==== Concurrency Level 100
86
- 776.40 [#/sec] (mean)